From 52a8d65cd5be0a2e09aa30d454d8580236a128cd Mon Sep 17 00:00:00 2001 From: johan pascal <johan.pascal@belledonne-communications.com> Date: Tue, 7 Jan 2025 22:10:25 +0100 Subject: [PATCH 1/5] PostQuantumCryptoEngine API update --- src/lime_crypto_primitives.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lime_crypto_primitives.cpp b/src/lime_crypto_primitives.cpp index 7000aba..10ebd7b 100644 --- a/src/lime_crypto_primitives.cpp +++ b/src/lime_crypto_primitives.cpp @@ -374,7 +374,7 @@ class bctbx_KEM : public KEM<Algo> { public: void createKeyPair(Kpair<Algo>&keyPair) override { std::vector<uint8_t> pk,sk; - m_ctx->crypto_kem_keypair(pk,sk); + m_ctx->keyGen(pk,sk); keyPair.publicKey().assign(pk.cbegin()); keyPair.privateKey().assign(sk.cbegin()); cleanBuffer(sk.data(), sk.size()); @@ -382,7 +382,7 @@ class bctbx_KEM : public KEM<Algo> { void encaps(const K<Algo, lime::Ktype::publicKey> &publicKey, K<Algo, lime::Ktype::cipherText> &cipherText, K<Algo, lime::Ktype::sharedSecret> &sharedSecret) override { std::vector<uint8_t> ct,ss; std::vector<uint8_t> pk(publicKey.cbegin(), publicKey.cend()); - m_ctx->crypto_kem_enc(ct, ss, pk); + m_ctx->encaps(ct, ss, pk); cipherText.assign(ct.cbegin()); sharedSecret.assign(ss.cbegin()); cleanBuffer(ss.data(), ss.size()); @@ -391,7 +391,7 @@ class bctbx_KEM : public KEM<Algo> { std::vector<uint8_t> ss; std::vector<uint8_t> sk(privateKey.cbegin(), privateKey.cend()); std::vector<uint8_t> ct(cipherText.cbegin(), cipherText.cend()); - m_ctx->crypto_kem_dec(ss, ct, sk); + m_ctx->decaps(ss, ct, sk); sharedSecret.assign(ss.cbegin()); cleanBuffer(ss.data(), ss.size()); cleanBuffer(sk.data(), sk.size()); @@ -512,10 +512,10 @@ template <> bool AEAD_decrypt<AES256GCM>(const uint8_t *const key, const size_t #endif //EC448_ENABLED #ifdef HAVE_BCTBXPQ - static_assert(bctoolbox::KYBER512::pkSize == K<K512, Ktype::publicKey>::ssize(), "bctoolbox and local defines mismatch"); - static_assert(bctoolbox::KYBER512::skSize == K<K512, Ktype::privateKey>::ssize(), "bctoolbox and local defines mismatch"); - static_assert(bctoolbox::KYBER512::ctSize == K<K512, Ktype::cipherText>::ssize(), "bctoolbox and local defines mismatch"); - static_assert(bctoolbox::KYBER512::ssSize == K<K512, Ktype::sharedSecret>::ssize(), "bctoolbox and local defines mismatch"); + static_assert(bctoolbox::KYBER512::kPkSize == K<K512, Ktype::publicKey>::ssize(), "bctoolbox and local defines mismatch"); + static_assert(bctoolbox::KYBER512::kSkSize == K<K512, Ktype::privateKey>::ssize(), "bctoolbox and local defines mismatch"); + static_assert(bctoolbox::KYBER512::kCtSize == K<K512, Ktype::cipherText>::ssize(), "bctoolbox and local defines mismatch"); + static_assert(bctoolbox::KYBER512::kSsSize == K<K512, Ktype::sharedSecret>::ssize(), "bctoolbox and local defines mismatch"); #endif //HAVE_BCTBXPQ /** * @brief force a buffer values to zero in a way that shall prevent the compiler from optimizing it out -- GitLab From 0b03eecde0b1a82c4c32114f026300dfcdfef4a6 Mon Sep 17 00:00:00 2001 From: johan pascal <johan.pascal@belledonne-communications.com> Date: Thu, 9 Jan 2025 17:49:01 +0100 Subject: [PATCH 2/5] Support C25519+MLKEM512 and C449+MLK1024 base algo --- include/lime/lime.hpp | 11 +- src/lime.cpp | 64 ++++++++- src/lime_crypto_primitives.cpp | 41 ++++-- src/lime_crypto_primitives.hpp | 15 +++ src/lime_double_ratchet.cpp | 15 ++- src/lime_double_ratchet.hpp | 11 ++ src/lime_double_ratchet_protocol.cpp | 11 ++ src/lime_double_ratchet_protocol.hpp | 11 ++ src/lime_impl.hpp | 9 ++ src/lime_keys.hpp | 83 ++++++++++-- src/lime_localStorage.cpp | 8 ++ src/lime_localStorage.hpp | 8 ++ src/lime_manager.cpp | 39 +++--- src/lime_x3dh.cpp | 6 + src/lime_x3dh.hpp | 6 + src/lime_x3dh_protocol.cpp | 26 ++++ src/lime_x3dh_protocol.hpp | 25 ++++ tester/CMakeLists.txt | 6 + tester/KEM_patterns.cpp | 14 +- tester/lime-tester-utils.cpp | 86 ++++++++++-- tester/lime-tester-utils.hpp | 10 ++ tester/lime_crypto-tester.cpp | 32 ++++- tester/lime_helloworld-tester.cpp | 12 ++ tester/lime_lime-tester.cpp | 187 ++++++++++++++++++++++++++- tester/lime_massive_group-tester.cpp | 136 +++++++++++++++---- tester/lime_multialgos-tester.cpp | 51 +++++++- tester/lime_multidomains-tester.cpp | 21 +++ tester/lime_server-tester.cpp | 32 ++++- 28 files changed, 867 insertions(+), 109 deletions(-) diff --git a/include/lime/lime.hpp b/include/lime/lime.hpp index bb25b9a..3377d5e 100644 --- a/include/lime/lime.hpp +++ b/include/lime/lime.hpp @@ -39,6 +39,8 @@ namespace lime { c25519=1, /**< Curve 25519 */ c448=2, /**< Curve 448-goldilocks */ c25519k512=3, /**< Hybrid KEM kyber512/curve 25519 */ + c25519mlk512=4, /**< Hybrid MLKEM 512/curve 25519 */ + c448mlk1024=5, /**< Hybrid MLKEM 1024/curve 448 */ }; /** Manage the encryption policy : how is the user's plaintext encrypted */ @@ -132,7 +134,8 @@ namespace lime { /** * convert a string to its curveId equivalent - * @param[in] algo the string to be converted. Valid inputs are c25519, c448, c25519k512 + * @param[in] algo the string to be converted. + * Valid inputs are c25519, c448, c25519k512, c25519mlk512, c448mlk1024 * @return the converted id, CurveId::unset on invalid input * */ lime::CurveId string2CurveId(const std::string &algo); @@ -158,7 +161,7 @@ namespace lime { std::string PeerDeviceStatus2String(const lime::PeerDeviceStatus status); /** - * @return true when PQ algorithms (c25519/k512 for now) are available + * @return true when PQ algorithms are available */ bool lime_is_PQ_available(void); @@ -235,7 +238,7 @@ namespace lime { * A user is published on an X3DH key server who must run using the same elliptic curve selected for this user (creation will fail otherwise), the server url cannot be changed later * * @param[in] localDeviceId Identify the local user account, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * @param[in] algos Choice of base algorithms used as base for cryptographic operation involved. An ordered list holding one or more of: CurveId::c25519, CurveId::c448, CurveId:c25519k512. + * @param[in] algos An ordered list of algorithms used as base for cryptographic operation involved. * @param[in] x3dhServerUrl The complete url(including port) of the X3DH key server. It must connect using HTTPS. Example: https://sip5.linphone.org:25519 * @param[in] OPkInitialBatchSize Number of OPks in the first batch uploaded to X3DH server * @param[in] callback This operation contact the X3DH server and is thus asynchronous, when server responds, @@ -302,7 +305,7 @@ namespace lime { * @note encryptionContext is shared pointers as the process being asynchronous, the ownership will be taken internally exempting caller to manage the buffers. * * @param[in] localDeviceId used to identify which local acount to use and also as the identified source of the message, shall be the GRUU - * @param[in] algos Choice of base algorithms used as base for cryptographic operation involved. An ordered list holding one or more of: CurveId::c25519, CurveId::c448, CurveId:c25519k512. + * @param[in] algos An ordered list of algorithms used as base for cryptographic operation involved. * @param[in,out] encryptionContext This context must persist during asynchronous calls to the lime X3DH server. It holds * - associated Data (recipientUserId or other) is used as associated data to ensure no-one can mess with intended recipient (when the recipientUserId is given) * - recipients a list of RecipientData holding: diff --git a/src/lime.cpp b/src/lime.cpp index a9c247e..6430c49 100644 --- a/src/lime.cpp +++ b/src/lime.cpp @@ -422,7 +422,13 @@ namespace lime { template class Lime<C448>; #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED template class Lime<C255K512>; + template class Lime<C255MLK512>; +#endif +#ifdef EC448_ENABLED + template class Lime<C448MLK1024>; +#endif #endif /****************************************************************************/ @@ -459,10 +465,18 @@ namespace lime { throw BCTBX_EXCEPTION << "Lime User creation asking to use Curve 448 but it's not supported - change lib lime compile option to enable it"; } #endif -#ifndef HAVE_BCTBXPQ +#if !defined(HAVE_BCTBXPQ) || !defined(EC25519_ENABLED) if (algo == lime::CurveId::c25519k512) { throw BCTBX_EXCEPTION << "Lime User creation asking to use Kyber512/Curve 25519 but it's not supported - change lib lime compile option to enable it"; } + if (algo == lime::CurveId::c25519mlk512) { + throw BCTBX_EXCEPTION << "Lime User creation asking to use MLKem512/Curve 25519 but it's not supported - change lib lime compile option to enable it"; + } +#endif +#if !defined(HAVE_BCTBXPQ) || !defined(EC448_ENABLED) + if (algo == lime::CurveId::c448mlk1024) { + throw BCTBX_EXCEPTION << "Lime User creation asking to use MLKem1024/Curve 448 but it's not supported - change lib lime compile option to enable it"; + } #endif //instanciate the correct Lime object @@ -489,7 +503,7 @@ namespace lime { break; case lime::CurveId::c25519k512 : -#ifdef HAVE_BCTBXPQ +#if defined(HAVE_BCTBXPQ) && defined(EC25519_ENABLED) { auto lime_ptr = std::make_shared<Lime<C255K512>>(localStorage, deviceId.getUsername(), url, X3DH_post_data); lime_ptr->publish_user(callback, OPkInitialBatchSize); @@ -497,6 +511,27 @@ namespace lime { } #endif break; + + case lime::CurveId::c25519mlk512 : +#if defined(HAVE_BCTBXPQ) && defined(EC25519_ENABLED) + { + auto lime_ptr = std::make_shared<Lime<C255MLK512>>(localStorage, deviceId.getUsername(), url, X3DH_post_data); + lime_ptr->publish_user(callback, OPkInitialBatchSize); + return std::static_pointer_cast<LimeGeneric>(lime_ptr); + } +#endif + break; + + case lime::CurveId::c448mlk1024 : +#if defined(HAVE_BCTBXPQ) && defined(EC448_ENABLED) + { + auto lime_ptr = std::make_shared<Lime<C448MLK1024>>(localStorage, deviceId.getUsername(), url, X3DH_post_data); + lime_ptr->publish_user(callback, OPkInitialBatchSize); + return std::static_pointer_cast<LimeGeneric>(lime_ptr); + } +#endif + break; + case lime::CurveId::unset : default: // asking for an unsupported type throw BCTBX_EXCEPTION << "Cannot create lime user "<<static_cast<std::string>(deviceId); @@ -532,10 +567,18 @@ namespace lime { throw BCTBX_EXCEPTION << "Lime load User "<<static_cast<std::string>(deviceId)<<" requests usage of Curve 448 but it's not supported - change lib lime compile option to enable it"; } #endif -#ifndef HAVE_BCTBXPQ +#if !defined(HAVE_BCTBXPQ) || !defined(EC25519_ENABLED) if (algo == lime::CurveId::c25519k512) { throw BCTBX_EXCEPTION << "Lime load User "<<static_cast<std::string>(deviceId)<<" requests usage of Kyber512/Curve 25519 but it's not supported - change lib lime compile option to enable it"; } + if (algo == lime::CurveId::c25519mlk512) { + throw BCTBX_EXCEPTION << "Lime load User "<<static_cast<std::string>(deviceId)<<" requests usage of MLKem512/Curve 25519 but it's not supported - change lib lime compile option to enable it"; + } +#endif +#if !defined(HAVE_BCTBXPQ) || !defined(EC448_ENABLED) + if (algo == lime::CurveId::c448mlk1024) { + throw BCTBX_EXCEPTION << "Lime load User "<<static_cast<std::string>(deviceId)<<" requests usage of MLKem1024/Curve 448 but it's not supported - change lib lime compile option to enable it"; + } #endif /* load user */ long int Uid=0; @@ -556,12 +599,25 @@ namespace lime { return std::make_shared<Lime<C448>>(localStorage, deviceId.getUsername(), x3dh_server_url, X3DH_post_data, Uid); #endif break; + case lime::CurveId::c25519k512 : -#ifdef HAVE_BCTBXPQ +#if defined(HAVE_BCTBXPQ) && defined(EC25519_ENABLED) return std::make_shared<Lime<C255K512>>(localStorage, deviceId.getUsername(), x3dh_server_url, X3DH_post_data, Uid); #endif break; + case lime::CurveId::c25519mlk512 : +#if defined(HAVE_BCTBXPQ) && defined(EC25519_ENABLED) + return std::make_shared<Lime<C255MLK512>>(localStorage, deviceId.getUsername(), x3dh_server_url, X3DH_post_data, Uid); +#endif + break; + + case lime::CurveId::c448mlk1024 : +#if defined(HAVE_BCTBXPQ) && defined(EC448_ENABLED) + return std::make_shared<Lime<C448MLK1024>>(localStorage, deviceId.getUsername(), x3dh_server_url, X3DH_post_data, Uid); +#endif + break; + case lime::CurveId::unset : default: // asking for an unsupported type throw BCTBX_EXCEPTION << "Cannot create load user "<<static_cast<std::string>(deviceId); diff --git a/src/lime_crypto_primitives.cpp b/src/lime_crypto_primitives.cpp index 10ebd7b..5e1edee 100644 --- a/src/lime_crypto_primitives.cpp +++ b/src/lime_crypto_primitives.cpp @@ -26,7 +26,6 @@ #endif /* HAVE_BCTBXPQ */ namespace lime { - /* template instanciations for Curves 25519 and 448, done */ #if EC25519_ENABLED template class X<C255, lime::Xtype::publicKey>; @@ -56,6 +55,16 @@ namespace lime { template class K<K512, lime::Ktype::cipherText>; template class K<K512, lime::Ktype::sharedSecret>; template class Kpair<K512>; + template class K<MLK512, lime::Ktype::publicKey>; + template class K<MLK512, lime::Ktype::privateKey>; + template class K<MLK512, lime::Ktype::cipherText>; + template class K<MLK512, lime::Ktype::sharedSecret>; + template class Kpair<MLK512>; + template class K<MLK1024, lime::Ktype::publicKey>; + template class K<MLK1024, lime::Ktype::privateKey>; + template class K<MLK1024, lime::Ktype::cipherText>; + template class K<MLK1024, lime::Ktype::sharedSecret>; + template class Kpair<MLK1024>; #endif /* HAVE_BCTBXPQ */ /***** Random Number Generator ********/ @@ -357,15 +366,21 @@ std::unique_ptr<bctoolbox::KEM> bctbx_KEMInit(void) { return nullptr; } - /* specialise KEM creation : K512 is Kyber512 */ - template <> std::unique_ptr<bctoolbox::KEM> bctbx_KEMInit<K512>(void) { - return std::make_unique<bctoolbox::KYBER512>(); - } +/* specialise KEM creation : K512 is Kyber512 */ +template <> std::unique_ptr<bctoolbox::KEM> bctbx_KEMInit<K512>(void) { + return std::make_unique<bctoolbox::KYBER512>(); +} +/* specialise KEM creation : MLK512 */ +template <> std::unique_ptr<bctoolbox::KEM> bctbx_KEMInit<MLK512>(void) { + return std::make_unique<bctoolbox::MLKEM512>(); +} +/* specialise KEM creation : MLK1024 */ +template <> std::unique_ptr<bctoolbox::KEM> bctbx_KEMInit<MLK1024>(void) { + return std::make_unique<bctoolbox::MLKEM1024>(); +} /** * @brief a wrapper around bctoolbox KEM algorithms, implements the key encapsulation mechanism interface - * - * Provides hybrid KEM curve 25519/Kyber512 */ template <typename Algo> class bctbx_KEM : public KEM<Algo> { @@ -397,7 +412,7 @@ class bctbx_KEM : public KEM<Algo> { cleanBuffer(sk.data(), sk.size()); } bctbx_KEM() { - m_ctx = bctbx_KEMInit<K512>(); + m_ctx = bctbx_KEMInit<Algo>(); } }; // class bctbx_KEM #endif //HAVE_BCTBXPQ @@ -511,12 +526,6 @@ template <> bool AEAD_decrypt<AES256GCM>(const uint8_t *const key, const size_t static_assert(BCTBX_EDDSA_448_SIGNATURE_SIZE == DSA<C448, DSAtype::signature>::ssize(), "bctoolbox and local defines mismatch"); #endif //EC448_ENABLED -#ifdef HAVE_BCTBXPQ - static_assert(bctoolbox::KYBER512::kPkSize == K<K512, Ktype::publicKey>::ssize(), "bctoolbox and local defines mismatch"); - static_assert(bctoolbox::KYBER512::kSkSize == K<K512, Ktype::privateKey>::ssize(), "bctoolbox and local defines mismatch"); - static_assert(bctoolbox::KYBER512::kCtSize == K<K512, Ktype::cipherText>::ssize(), "bctoolbox and local defines mismatch"); - static_assert(bctoolbox::KYBER512::kSsSize == K<K512, Ktype::sharedSecret>::ssize(), "bctoolbox and local defines mismatch"); -#endif //HAVE_BCTBXPQ /** * @brief force a buffer values to zero in a way that shall prevent the compiler from optimizing it out * @@ -544,5 +553,9 @@ void cleanBuffer(uint8_t *buffer, size_t size) { #ifdef HAVE_BCTBXPQ template class bctbx_KEM<K512>; template std::shared_ptr<KEM<K512>> make_KEM(); + template class bctbx_KEM<MLK512>; + template std::shared_ptr<KEM<MLK512>> make_KEM(); + template class bctbx_KEM<MLK1024>; + template std::shared_ptr<KEM<MLK1024>> make_KEM(); #endif //HAVE_BCTBXPQ } // namespace lime diff --git a/src/lime_crypto_primitives.hpp b/src/lime_crypto_primitives.hpp index 4258e9b..905cb89 100644 --- a/src/lime_crypto_primitives.hpp +++ b/src/lime_crypto_primitives.hpp @@ -529,12 +529,27 @@ std::shared_ptr<KEM<Algo>> make_KEM(); #endif // EC448_ENABLED #ifdef HAVE_BCTBXPQ + // Kyber512 extern template std::shared_ptr<KEM<K512>> make_KEM(); extern template class K<K512, lime::Ktype::publicKey>; extern template class K<K512, lime::Ktype::privateKey>; extern template class K<K512, lime::Ktype::cipherText>; extern template class K<K512, lime::Ktype::sharedSecret>; extern template class Kpair<K512>; + // MLKEM 512 + extern template std::shared_ptr<KEM<MLK512>> make_KEM(); + extern template class K<MLK512, lime::Ktype::publicKey>; + extern template class K<MLK512, lime::Ktype::privateKey>; + extern template class K<MLK512, lime::Ktype::cipherText>; + extern template class K<MLK512, lime::Ktype::sharedSecret>; + extern template class Kpair<MLK512>; + // MLKEM 1024 + extern template std::shared_ptr<KEM<MLK1024>> make_KEM(); + extern template class K<MLK1024, lime::Ktype::publicKey>; + extern template class K<MLK1024, lime::Ktype::privateKey>; + extern template class K<MLK1024, lime::Ktype::cipherText>; + extern template class K<MLK1024, lime::Ktype::sharedSecret>; + extern template class Kpair<MLK1024>; #endif //HAVE_BCTBXPQ } // namespace lime diff --git a/src/lime_double_ratchet.cpp b/src/lime_double_ratchet.cpp index c84f48a..6017884 100644 --- a/src/lime_double_ratchet.cpp +++ b/src/lime_double_ratchet.cpp @@ -1537,7 +1537,6 @@ namespace lime { /* template instanciations */ #ifdef EC25519_ENABLED template class DRi<C255>; - template std::shared_ptr<DR> make_DR_from_localStorage<C255>(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context); template std::shared_ptr<DR> make_DR_for_sender(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARrKey<C255> &peerPublicKey, long int peerDid, const std::string &peerDeviceId, const DSA<C255::EC, lime::DSAtype::publicKey> &peerIk, long int selfDid, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context); template std::shared_ptr<DR> make_DR_for_receiver(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARsKey<C255> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const uint32_t OPk_id, const DSA<C255::EC, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, std::shared_ptr<RNG> RNG_context); @@ -1545,17 +1544,29 @@ namespace lime { #ifdef EC448_ENABLED template class DRi<C448>; - template std::shared_ptr<DR> make_DR_from_localStorage<C448>(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context); template std::shared_ptr<DR> make_DR_for_sender(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARrKey<C448> &peerPublicKey, long int peerDid, const std::string &peerDeviceId, const DSA<C448::EC, lime::DSAtype::publicKey> &peerIk, long int selfDid, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context); template std::shared_ptr<DR> make_DR_for_receiver(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARsKey<C448> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const uint32_t OPk_id, const DSA<C448::EC, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, std::shared_ptr<RNG> RNG_context); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED template class DRi<C255K512>; template std::shared_ptr<DR> make_DR_from_localStorage<C255K512>(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context); template std::shared_ptr<DR> make_DR_for_sender(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARrKey<C255K512> &peerPublicKey, long int peerDid, const std::string &peerDeviceId, const DSA<C255K512::EC, lime::DSAtype::publicKey> &peerIk, long int selfDid, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context); template std::shared_ptr<DR> make_DR_for_receiver(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARsKey<C255K512> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const uint32_t OPk_id, const DSA<C255K512::EC, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, std::shared_ptr<RNG> RNG_context); + + template class DRi<C255MLK512>; + template std::shared_ptr<DR> make_DR_from_localStorage<C255MLK512>(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context); + template std::shared_ptr<DR> make_DR_for_sender(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARrKey<C255MLK512> &peerPublicKey, long int peerDid, const std::string &peerDeviceId, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &peerIk, long int selfDid, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context); + template std::shared_ptr<DR> make_DR_for_receiver(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARsKey<C255MLK512> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const uint32_t OPk_id, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, std::shared_ptr<RNG> RNG_context); +#endif +#ifdef EC448_ENABLED + template class DRi<C448MLK1024>; + template std::shared_ptr<DR> make_DR_from_localStorage<C448MLK1024>(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context); + template std::shared_ptr<DR> make_DR_for_sender(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARrKey<C448MLK1024> &peerPublicKey, long int peerDid, const std::string &peerDeviceId, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &peerIk, long int selfDid, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context); + template std::shared_ptr<DR> make_DR_for_receiver(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARsKey<C448MLK1024> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const uint32_t OPk_id, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, std::shared_ptr<RNG> RNG_context); #endif +#endif // HAVE_BCTBXPQ /** * @brief Encrypt a message to all recipients, identified by their device id diff --git a/src/lime_double_ratchet.hpp b/src/lime_double_ratchet.hpp index 4c9256b..7a09b90 100644 --- a/src/lime_double_ratchet.hpp +++ b/src/lime_double_ratchet.hpp @@ -364,10 +364,21 @@ namespace lime { #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED extern template std::shared_ptr<DR> make_DR_from_localStorage<C255K512>(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context); extern template std::shared_ptr<DR> make_DR_for_sender(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARrKey<C255K512> &peerPublicKey, long int peerDid, const std::string &peerDeviceId, const DSA<C255K512::EC, lime::DSAtype::publicKey> &peerIk, long int selfDid, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context); extern template std::shared_ptr<DR> make_DR_for_receiver(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARsKey<C255K512> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const uint32_t OPk_id, const DSA<C255K512::EC, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, std::shared_ptr<RNG> RNG_context); + + extern template std::shared_ptr<DR> make_DR_from_localStorage<C255MLK512>(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context); + extern template std::shared_ptr<DR> make_DR_for_sender(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARrKey<C255MLK512> &peerPublicKey, long int peerDid, const std::string &peerDeviceId, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &peerIk, long int selfDid, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context); + extern template std::shared_ptr<DR> make_DR_for_receiver(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARsKey<C255MLK512> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const uint32_t OPk_id, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, std::shared_ptr<RNG> RNG_context); +#endif +#ifdef EC448_ENABLED + extern template std::shared_ptr<DR> make_DR_from_localStorage<C448MLK1024>(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context); + extern template std::shared_ptr<DR> make_DR_for_sender(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARrKey<C448MLK1024> &peerPublicKey, long int peerDid, const std::string &peerDeviceId, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &peerIk, long int selfDid, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context); + extern template std::shared_ptr<DR> make_DR_for_receiver(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const ARsKey<C448MLK1024> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const uint32_t OPk_id, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, std::shared_ptr<RNG> RNG_context); #endif +#endif // HAVE_BCTBXPQ } diff --git a/src/lime_double_ratchet_protocol.cpp b/src/lime_double_ratchet_protocol.cpp index 3c302a8..88704e2 100644 --- a/src/lime_double_ratchet_protocol.cpp +++ b/src/lime_double_ratchet_protocol.cpp @@ -291,9 +291,20 @@ namespace lime { template bool parseMessage_get_X3DHinit<C448>(const std::vector<uint8_t> &message, std::vector<uint8_t> &X3DH_initMessage) noexcept; #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED template void buildMessage_X3DHinit<C255K512>(std::vector<uint8_t> &message, const DSA<C255K512::EC, lime::DSAtype::publicKey> &Ik, const X<C255K512::EC, lime::Xtype::publicKey> &Ek, const K<C255K512::KEM, lime::Ktype::cipherText> &Ct, const uint32_t SPk_id, const uint32_t OPk_id, const bool OPk_flag) noexcept; template void parseMessage_X3DHinit<C255K512>(const std::vector<uint8_t>message, DSA<C255K512::EC, lime::DSAtype::publicKey> &Ik, X<C255K512::EC, lime::Xtype::publicKey> &Ek, K<C255K512::KEM, lime::Ktype::cipherText> &Ct, uint32_t &SPk_id, uint32_t &OPk_id, bool &OPk_flag) noexcept; template bool parseMessage_get_X3DHinit<C255K512>(const std::vector<uint8_t> &message, std::vector<uint8_t> &X3DH_initMessage) noexcept; + + template void buildMessage_X3DHinit<C255MLK512>(std::vector<uint8_t> &message, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &Ik, const X<C255MLK512::EC, lime::Xtype::publicKey> &Ek, const K<C255MLK512::KEM, lime::Ktype::cipherText> &Ct, const uint32_t SPk_id, const uint32_t OPk_id, const bool OPk_flag) noexcept; + template void parseMessage_X3DHinit<C255MLK512>(const std::vector<uint8_t>message, DSA<C255MLK512::EC, lime::DSAtype::publicKey> &Ik, X<C255MLK512::EC, lime::Xtype::publicKey> &Ek, K<C255MLK512::KEM, lime::Ktype::cipherText> &Ct, uint32_t &SPk_id, uint32_t &OPk_id, bool &OPk_flag) noexcept; + template bool parseMessage_get_X3DHinit<C255MLK512>(const std::vector<uint8_t> &message, std::vector<uint8_t> &X3DH_initMessage) noexcept; +#endif +#ifdef EC448_ENABLED + template void buildMessage_X3DHinit<C448MLK1024>(std::vector<uint8_t> &message, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &Ik, const X<C448MLK1024::EC, lime::Xtype::publicKey> &Ek, const K<C448MLK1024::KEM, lime::Ktype::cipherText> &Ct, const uint32_t SPk_id, const uint32_t OPk_id, const bool OPk_flag) noexcept; + template void parseMessage_X3DHinit<C448MLK1024>(const std::vector<uint8_t>message, DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &Ik, X<C448MLK1024::EC, lime::Xtype::publicKey> &Ek, K<C448MLK1024::KEM, lime::Ktype::cipherText> &Ct, uint32_t &SPk_id, uint32_t &OPk_id, bool &OPk_flag) noexcept; + template bool parseMessage_get_X3DHinit<C448MLK1024>(const std::vector<uint8_t> &message, std::vector<uint8_t> &X3DH_initMessage) noexcept; +#endif #endif //HAVE_BCTBXPQ } // namespace double_ratchet_protocol diff --git a/src/lime_double_ratchet_protocol.hpp b/src/lime_double_ratchet_protocol.hpp index 3da6552..724de22 100644 --- a/src/lime_double_ratchet_protocol.hpp +++ b/src/lime_double_ratchet_protocol.hpp @@ -133,9 +133,20 @@ namespace lime { #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED extern template void buildMessage_X3DHinit<C255K512>(std::vector<uint8_t> &message, const DSA<C255K512::EC, lime::DSAtype::publicKey> &Ik, const X<C255K512::EC, lime::Xtype::publicKey> &Ek, const K<C255K512::KEM, lime::Ktype::cipherText> &Ct, const uint32_t SPk_id, const uint32_t OPk_id, const bool OPk_flag) noexcept; extern template void parseMessage_X3DHinit<C255K512>(const std::vector<uint8_t>message, DSA<C255K512::EC, lime::DSAtype::publicKey> &Ik, X<C255K512::EC, lime::Xtype::publicKey> &Ek, K<C255K512::KEM, lime::Ktype::cipherText> &Ct, uint32_t &SPk_id, uint32_t &OPk_id, bool &OPk_flag) noexcept; extern template bool parseMessage_get_X3DHinit<C255K512>(const std::vector<uint8_t> &message, std::vector<uint8_t> &X3DH_initMessage) noexcept; + + extern template void buildMessage_X3DHinit<C255MLK512>(std::vector<uint8_t> &message, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &Ik, const X<C255MLK512::EC, lime::Xtype::publicKey> &Ek, const K<C255MLK512::KEM, lime::Ktype::cipherText> &Ct, const uint32_t SPk_id, const uint32_t OPk_id, const bool OPk_flag) noexcept; + extern template void parseMessage_X3DHinit<C255MLK512>(const std::vector<uint8_t>message, DSA<C255MLK512::EC, lime::DSAtype::publicKey> &Ik, X<C255MLK512::EC, lime::Xtype::publicKey> &Ek, K<C255MLK512::KEM, lime::Ktype::cipherText> &Ct, uint32_t &SPk_id, uint32_t &OPk_id, bool &OPk_flag) noexcept; + extern template bool parseMessage_get_X3DHinit<C255MLK512>(const std::vector<uint8_t> &message, std::vector<uint8_t> &X3DH_initMessage) noexcept; +#endif +#ifdef EC448_ENABLED + extern template void buildMessage_X3DHinit<C448MLK1024>(std::vector<uint8_t> &message, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &Ik, const X<C448MLK1024::EC, lime::Xtype::publicKey> &Ek, const K<C448MLK1024::KEM, lime::Ktype::cipherText> &Ct, const uint32_t SPk_id, const uint32_t OPk_id, const bool OPk_flag) noexcept; + extern template void parseMessage_X3DHinit<C448MLK1024>(const std::vector<uint8_t>message, DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &Ik, X<C448MLK1024::EC, lime::Xtype::publicKey> &Ek, K<C448MLK1024::KEM, lime::Ktype::cipherText> &Ct, uint32_t &SPk_id, uint32_t &OPk_id, bool &OPk_flag) noexcept; + extern template bool parseMessage_get_X3DHinit<C448MLK1024>(const std::vector<uint8_t> &message, std::vector<uint8_t> &X3DH_initMessage) noexcept; +#endif #endif //HAVE_BCTBXPQ diff --git a/src/lime_impl.hpp b/src/lime_impl.hpp index 6335ee7..e77b2b5 100644 --- a/src/lime_impl.hpp +++ b/src/lime_impl.hpp @@ -141,6 +141,15 @@ namespace lime { #ifdef EC448_ENABLED extern template class Lime<C448>; #endif +#ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED + extern template class Lime<C255K512>; + extern template class Lime<C255MLK512>; +#endif +#ifdef EC448_ENABLED + extern template class Lime<C448MLK1024>; +#endif +#endif } #endif /* lime_impl_hpp */ diff --git a/src/lime_keys.hpp b/src/lime_keys.hpp index bb8ae2c..14e7d1f 100644 --- a/src/lime_keys.hpp +++ b/src/lime_keys.hpp @@ -24,6 +24,10 @@ #include <array> #include <iterator> #include "lime/lime.hpp" +#include "bctoolbox/crypto.hh" +#ifdef HAVE_BCTBXPQ +#include "postquantumcryptoengine/crypto.hh" +#endif /* HAVE_BCTBXPQ */ namespace lime { // Data structure type enumerations @@ -59,9 +63,9 @@ namespace lime { /// the C25519 curve id using the CurveId enumeration static constexpr lime::CurveId curveId() {return lime::CurveId::c25519;}; /// for X25519, public, private and shared secret have the same length: 32 bytes - static constexpr size_t Xsize(lime::Xtype dataType) {return 32;}; + static constexpr size_t Xsize(lime::Xtype dataType) {return BCTBX_ECDH_X25519_PUBLIC_SIZE;}; /// for Ed25519, public and private key have the same length: 32 bytes, signature is 64 bytes long - static constexpr size_t DSAsize(lime::DSAtype dataType) {return (dataType != lime::DSAtype::signature)?32:64;}; + static constexpr size_t DSAsize(lime::DSAtype dataType) {return (dataType != lime::DSAtype::signature)?BCTBX_EDDSA_25519_PUBLIC_SIZE:BCTBX_EDDSA_25519_SIGNATURE_SIZE;}; }; /** @@ -74,9 +78,9 @@ namespace lime { ///the C448 curve id using the CurveId enumeration static constexpr lime::CurveId curveId() {return lime::CurveId::c448;}; /// for X448, public, private and shared secret have the same length 56 bytes - static constexpr size_t Xsize(lime::Xtype dataType) {return 56;}; + static constexpr size_t Xsize(lime::Xtype dataType) {return BCTBX_ECDH_X448_PUBLIC_SIZE;}; /// for Ed448, public and private key have the same length 57 bytes, signature is 114 bytes long - static constexpr size_t DSAsize(lime::DSAtype dataType) {return (dataType != lime::DSAtype::signature)?57:114;}; + static constexpr size_t DSAsize(lime::DSAtype dataType) {return (dataType != lime::DSAtype::signature)?BCTBX_EDDSA_448_PUBLIC_SIZE:BCTBX_EDDSA_448_SIGNATURE_SIZE;}; }; struct genericKEM { @@ -93,27 +97,90 @@ namespace lime { static constexpr size_t Ksize(lime::Ktype dataType) { switch (dataType) { case lime::Ktype::publicKey: - return 800; + return bctoolbox::KYBER512::kPkSize; break; case lime::Ktype::privateKey: - return 1632; + return bctoolbox::KYBER512::kSkSize; break; case lime::Ktype::cipherText: - return 768; + return bctoolbox::KYBER512::kCtSize; break; case lime::Ktype::sharedSecret: - return 32; + return bctoolbox::KYBER512::kSsSize; break; } return 0; // make compiler happy }; }; + /** + * @brief MLKEM 512 KEM data types size definition + */ + struct MLK512: public genericKEM { + /// a string to indentify this curve + static const std::string Id(void) {return std::string("MLKEM512");}; + /// mlkem512 + static constexpr size_t Ksize(lime::Ktype dataType) { + switch (dataType) { + case lime::Ktype::publicKey: + return bctoolbox::MLKEM512::kPkSize; + break; + case lime::Ktype::privateKey: + return bctoolbox::MLKEM512::kSkSize; + break; + case lime::Ktype::cipherText: + return bctoolbox::MLKEM512::kCtSize; + break; + case lime::Ktype::sharedSecret: + return bctoolbox::MLKEM512::kSsSize; + break; + } + return 0; // make compiler happy + }; + }; + + /** + * @brief MLKEM 1024 KEM data types size definition + */ + struct MLK1024: public genericKEM { + /// a string to indentify this curve + static const std::string Id(void) {return std::string("MLKEM1024");}; + /// mlkem1024 + static constexpr size_t Ksize(lime::Ktype dataType) { + switch (dataType) { + case lime::Ktype::publicKey: + return bctoolbox::MLKEM1024::kPkSize; + break; + case lime::Ktype::privateKey: + return bctoolbox::MLKEM1024::kSkSize; + break; + case lime::Ktype::cipherText: + return bctoolbox::MLKEM1024::kCtSize; + break; + case lime::Ktype::sharedSecret: + return bctoolbox::MLKEM1024::kSsSize; + break; + } + return 0; // make compiler happy + }; + }; + + // Hybrids: c25519/kyber512 c25519/mlkem512, c448/mlkem1024 struct C255K512: public C255,K512 { static constexpr lime::CurveId curveId(void) {return lime::CurveId::c25519k512;}; using EC = C255; using KEM = K512; }; + struct C255MLK512: public C255,MLK512 { + static constexpr lime::CurveId curveId(void) {return lime::CurveId::c25519mlk512;}; + using EC = C255; + using KEM = MLK512; + }; + struct C448MLK1024: public C448,MLK1024 { + static constexpr lime::CurveId curveId(void) {return lime::CurveId::c448mlk1024;}; + using EC = C448; + using KEM = MLK1024; + }; #endif // HAVE_BCTBXPQ // Hash function defines diff --git a/src/lime_localStorage.cpp b/src/lime_localStorage.cpp index cdf1174..4b56e4c 100644 --- a/src/lime_localStorage.cpp +++ b/src/lime_localStorage.cpp @@ -789,7 +789,15 @@ void Db::rollback_transaction() template long int Db::store_peerDevice<C448>(const std::string &peerDeviceId, const DSA<C448, lime::DSAtype::publicKey> &Ik); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED template long int Db::check_peerDevice<C255K512>(const std::string &peerDeviceId, const DSA<C255K512::EC, lime::DSAtype::publicKey> &Ik, const bool updateInvalid); template long int Db::store_peerDevice<C255K512>(const std::string &peerDeviceId, const DSA<C255K512::EC, lime::DSAtype::publicKey> &Ik); + template long int Db::check_peerDevice<C255MLK512>(const std::string &peerDeviceId, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &Ik, const bool updateInvalid); + template long int Db::store_peerDevice<C255MLK512>(const std::string &peerDeviceId, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &Ik); +#endif +#ifdef EC448_ENABLED + template long int Db::check_peerDevice<C448MLK1024>(const std::string &peerDeviceId, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &Ik, const bool updateInvalid); + template long int Db::store_peerDevice<C448MLK1024>(const std::string &peerDeviceId, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &Ik); #endif +#endif // HAVE_BCTBXPQ } // namespace lime diff --git a/src/lime_localStorage.hpp b/src/lime_localStorage.hpp index b547a80..72c3a66 100644 --- a/src/lime_localStorage.hpp +++ b/src/lime_localStorage.hpp @@ -79,9 +79,17 @@ namespace lime { extern template long int Db::store_peerDevice<C448>(const std::string &peerDeviceId, const DSA<C448, lime::DSAtype::publicKey> &Ik); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED extern template long int Db::check_peerDevice<C255K512>(const std::string &peerDeviceId, const DSA<C255K512::EC, lime::DSAtype::publicKey> &Ik, const bool updateInvalid); extern template long int Db::store_peerDevice<C255K512>(const std::string &peerDeviceId, const DSA<C255K512::EC, lime::DSAtype::publicKey> &Ik); + extern template long int Db::check_peerDevice<C255MLK512>(const std::string &peerDeviceId, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &Ik, const bool updateInvalid); + extern template long int Db::store_peerDevice<C255MLK512>(const std::string &peerDeviceId, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &Ik); +#endif +#ifdef EC448_ENABLED + extern template long int Db::check_peerDevice<C448MLK1024>(const std::string &peerDeviceId, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &Ik, const bool updateInvalid); + extern template long int Db::store_peerDevice<C448MLK1024>(const std::string &peerDeviceId, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &Ik); #endif +#endif // HAVE_BCTBXPQ } diff --git a/src/lime_manager.cpp b/src/lime_manager.cpp index f8a9cbe..5c01d7d 100644 --- a/src/lime_manager.cpp +++ b/src/lime_manager.cpp @@ -439,32 +439,35 @@ namespace lime { /* Lime utils functions */ /* */ /****************************************************************************/ +namespace { + // a mapping from string to the curveId enum + const std::unordered_map<std::string, lime::CurveId> string2CurveIdMap = { + {"c25519", lime::CurveId::c25519}, + {"c448", lime::CurveId::c448}, + {"c25519k512", lime::CurveId::c25519k512}, + {"c25519mlk512", lime::CurveId::c25519mlk512}, + {"c448mlk1024", lime::CurveId::c448mlk1024}, + }; +} lime::CurveId string2CurveId(const std::string &algo) { - lime::CurveId curve = lime::CurveId::unset; // default to unset - if (algo.compare("c448") == 0) { - curve = lime::CurveId::c448; - } else if (algo.compare("c25519k512") == 0) { - curve = lime::CurveId::c25519k512; - } else if (algo.compare("c25519") == 0) { - curve = lime::CurveId::c25519; + auto it = string2CurveIdMap.find(algo); + if (it != string2CurveIdMap.end()) { + return it->second; + } else { + return lime::CurveId::unset; // unmatching input string } - return curve; } std::string CurveId2String(const lime::CurveId algo) { - switch (algo) { - case lime::CurveId::c25519: - return "c25519"; - case lime::CurveId::c448: - return "c448"; - case lime::CurveId::c25519k512: - return "c25519k512"; - case lime::CurveId::unset: - default: - return "unset"; + for (const auto &e : string2CurveIdMap) { + if (e.second == algo) { + return e.first; + } } + return "unset"; } + std::string CurveId2String(const std::vector<lime::CurveId> algos, const std::string separator) { std::ostringstream csvAlgos; auto first = true; diff --git a/src/lime_x3dh.cpp b/src/lime_x3dh.cpp index 3ec816f..039d8f1 100644 --- a/src/lime_x3dh.cpp +++ b/src/lime_x3dh.cpp @@ -1403,6 +1403,12 @@ namespace lime { template std::shared_ptr<X3DH> make_X3DH<C448>(std::shared_ptr<lime::Db> localStorage, const std::string &selfDeviceId,const std::string &X3DHServerURL, const limeX3DHServerPostData &X3DH_post_data, std::shared_ptr<RNG> RNG_context, const long Uid); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED template std::shared_ptr<X3DH> make_X3DH<C255K512>(std::shared_ptr<lime::Db> localStorage, const std::string &selfDeviceId, const std::string &X3DHServerURL, const limeX3DHServerPostData &X3DH_post_data, std::shared_ptr<RNG> RNG_context, const long Uid); + template std::shared_ptr<X3DH> make_X3DH<C255MLK512>(std::shared_ptr<lime::Db> localStorage, const std::string &selfDeviceId, const std::string &X3DHServerURL, const limeX3DHServerPostData &X3DH_post_data, std::shared_ptr<RNG> RNG_context, const long Uid); +#endif +#ifdef EC448_ENABLED + template std::shared_ptr<X3DH> make_X3DH<C448MLK1024>(std::shared_ptr<lime::Db> localStorage, const std::string &selfDeviceId, const std::string &X3DHServerURL, const limeX3DHServerPostData &X3DH_post_data, std::shared_ptr<RNG> RNG_context, const long Uid); +#endif #endif } // namespace lime diff --git a/src/lime_x3dh.hpp b/src/lime_x3dh.hpp index 06507ce..e38a9f8 100644 --- a/src/lime_x3dh.hpp +++ b/src/lime_x3dh.hpp @@ -410,7 +410,13 @@ namespace lime { extern template std::shared_ptr<X3DH> make_X3DH<C448>(std::shared_ptr<lime::Db> localStorage, const std::string &selfDeviceId, const std::string &X3DHServerURL, const limeX3DHServerPostData &X3DH_post_data, std::shared_ptr<RNG> RNG_context, const long Uid); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED extern template std::shared_ptr<X3DH> make_X3DH<C255K512>(std::shared_ptr<lime::Db> localStorage, const std::string &selfDeviceId, const std::string &X3DHServerURL, const limeX3DHServerPostData &X3DH_post_data, std::shared_ptr<RNG> RNG_context, const long Uid); + extern template std::shared_ptr<X3DH> make_X3DH<C255MLK512>(std::shared_ptr<lime::Db> localStorage, const std::string &selfDeviceId, const std::string &X3DHServerURL, const limeX3DHServerPostData &X3DH_post_data, std::shared_ptr<RNG> RNG_context, const long Uid); +#endif +#ifdef EC448_ENABLED + extern template std::shared_ptr<X3DH> make_X3DH<C448MLK1024>(std::shared_ptr<lime::Db> localStorage, const std::string &selfDeviceId, const std::string &X3DHServerURL, const limeX3DHServerPostData &X3DH_post_data, std::shared_ptr<RNG> RNG_context, const long Uid); +#endif #endif } //namespace lime #endif /* lime_x3dh_hpp */ diff --git a/src/lime_x3dh_protocol.cpp b/src/lime_x3dh_protocol.cpp index c8684f4..4623acb 100644 --- a/src/lime_x3dh_protocol.cpp +++ b/src/lime_x3dh_protocol.cpp @@ -656,6 +656,8 @@ namespace lime { template bool parseMessage_selfOPks<C448>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept; #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED + // C25519/Kyber512 template void buildMessage_registerUser<C255K512>(std::vector<uint8_t> &message, const DSA<C255K512::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<C255K512> &SPk, const std::vector<OneTimePreKey<C255K512>> &OPks) noexcept; template void buildMessage_deleteUser<C255K512>(std::vector<uint8_t> &message) noexcept; template void buildMessage_publishSPk<C255K512>(std::vector<uint8_t> &message, const SignedPreKey<C255K512> &SPk) noexcept; @@ -665,6 +667,30 @@ namespace lime { template bool parseMessage_getType<C255K512>(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept; template bool parseMessage_getPeerBundles<C255K512>(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<C255K512>> &peersBundle) noexcept; template bool parseMessage_selfOPks<C255K512>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept; + + // C25519/MLKem512 + template void buildMessage_registerUser<C255MLK512>(std::vector<uint8_t> &message, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<C255MLK512> &SPk, const std::vector<OneTimePreKey<C255MLK512>> &OPks) noexcept; + template void buildMessage_deleteUser<C255MLK512>(std::vector<uint8_t> &message) noexcept; + template void buildMessage_publishSPk<C255MLK512>(std::vector<uint8_t> &message, const SignedPreKey<C255MLK512> &SPk) noexcept; + template void buildMessage_publishOPks<C255MLK512>(std::vector<uint8_t> &message, const std::vector<OneTimePreKey<C255MLK512>> &OPks) noexcept; + template void buildMessage_getPeerBundles<C255MLK512>(std::vector<uint8_t> &message, std::vector<std::string> &peer_device_ids) noexcept; + template void buildMessage_getSelfOPks<C255MLK512>(std::vector<uint8_t> &message) noexcept; + template bool parseMessage_getType<C255MLK512>(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept; + template bool parseMessage_getPeerBundles<C255MLK512>(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<C255MLK512>> &peersBundle) noexcept; + template bool parseMessage_selfOPks<C255MLK512>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept; +#endif +#ifdef EC448_ENABLED + // C448/MLKem1024 + template void buildMessage_registerUser<C448MLK1024>(std::vector<uint8_t> &message, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<C448MLK1024> &SPk, const std::vector<OneTimePreKey<C448MLK1024>> &OPks) noexcept; + template void buildMessage_deleteUser<C448MLK1024>(std::vector<uint8_t> &message) noexcept; + template void buildMessage_publishSPk<C448MLK1024>(std::vector<uint8_t> &message, const SignedPreKey<C448MLK1024> &SPk) noexcept; + template void buildMessage_publishOPks<C448MLK1024>(std::vector<uint8_t> &message, const std::vector<OneTimePreKey<C448MLK1024>> &OPks) noexcept; + template void buildMessage_getPeerBundles<C448MLK1024>(std::vector<uint8_t> &message, std::vector<std::string> &peer_device_ids) noexcept; + template void buildMessage_getSelfOPks<C448MLK1024>(std::vector<uint8_t> &message) noexcept; + template bool parseMessage_getType<C448MLK1024>(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept; + template bool parseMessage_getPeerBundles<C448MLK1024>(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<C448MLK1024>> &peersBundle) noexcept; + template bool parseMessage_selfOPks<C448MLK1024>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept; #endif +#endif // HAVE_BCTBXPQ } //namespace x3dh_protocol } //namespace lime diff --git a/src/lime_x3dh_protocol.hpp b/src/lime_x3dh_protocol.hpp index 3afc2d6..4cf921d 100644 --- a/src/lime_x3dh_protocol.hpp +++ b/src/lime_x3dh_protocol.hpp @@ -169,6 +169,8 @@ namespace lime { #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED + // C25519/Kyber512 extern template void buildMessage_registerUser<C255K512>(std::vector<uint8_t> &message, const DSA<C255K512::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<C255K512> &SPk, const std::vector<OneTimePreKey<C255K512>> &OPks) noexcept; extern template void buildMessage_deleteUser<C255K512>(std::vector<uint8_t> &message) noexcept; extern template void buildMessage_publishSPk<C255K512>(std::vector<uint8_t> &message, const SignedPreKey<C255K512> &SPk) noexcept; @@ -178,7 +180,30 @@ namespace lime { extern template bool parseMessage_getType<C255K512>(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept; extern template bool parseMessage_getPeerBundles<C255K512>(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<C255K512>> &peersBundle) noexcept; extern template bool parseMessage_selfOPks<C255K512>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept; + // C25519/MLKem512 + extern template void buildMessage_registerUser<C255MLK512>(std::vector<uint8_t> &message, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<C255MLK512> &SPk, const std::vector<OneTimePreKey<C255MLK512>> &OPks) noexcept; + extern template void buildMessage_deleteUser<C255MLK512>(std::vector<uint8_t> &message) noexcept; + extern template void buildMessage_publishSPk<C255MLK512>(std::vector<uint8_t> &message, const SignedPreKey<C255MLK512> &SPk) noexcept; + extern template void buildMessage_publishOPks<C255MLK512>(std::vector<uint8_t> &message, const std::vector<OneTimePreKey<C255MLK512>> &OPks) noexcept; + extern template void buildMessage_getPeerBundles<C255MLK512>(std::vector<uint8_t> &message, std::vector<std::string> &peer_device_ids) noexcept; + extern template void buildMessage_getSelfOPks<C255MLK512>(std::vector<uint8_t> &message) noexcept; + extern template bool parseMessage_getType<C255MLK512>(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept; + extern template bool parseMessage_getPeerBundles<C255MLK512>(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<C255MLK512>> &peersBundle) noexcept; + extern template bool parseMessage_selfOPks<C255MLK512>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept; +#endif +#ifdef EC448_ENABLED + // C448/MLKem1024 + extern template void buildMessage_registerUser<C448MLK1024>(std::vector<uint8_t> &message, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<C448MLK1024> &SPk, const std::vector<OneTimePreKey<C448MLK1024>> &OPks) noexcept; + extern template void buildMessage_deleteUser<C448MLK1024>(std::vector<uint8_t> &message) noexcept; + extern template void buildMessage_publishSPk<C448MLK1024>(std::vector<uint8_t> &message, const SignedPreKey<C448MLK1024> &SPk) noexcept; + extern template void buildMessage_publishOPks<C448MLK1024>(std::vector<uint8_t> &message, const std::vector<OneTimePreKey<C448MLK1024>> &OPks) noexcept; + extern template void buildMessage_getPeerBundles<C448MLK1024>(std::vector<uint8_t> &message, std::vector<std::string> &peer_device_ids) noexcept; + extern template void buildMessage_getSelfOPks<C448MLK1024>(std::vector<uint8_t> &message) noexcept; + extern template bool parseMessage_getType<C448MLK1024>(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept; + extern template bool parseMessage_getPeerBundles<C448MLK1024>(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<C448MLK1024>> &peersBundle) noexcept; + extern template bool parseMessage_selfOPks<C448MLK1024>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept; #endif +#endif // HAVE_BCTBXPQ } // namespace x3dh_protocol } // namespace lime diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index 1ccd644..fd770a6 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -53,6 +53,9 @@ find_package (Threads REQUIRED) if(ANDROID OR IOS) add_library(limetester SHARED ${HEADER_FILES_CXX} ${SOURCE_FILES_CXX} ${SOURCE_FILES_C} ) target_link_libraries(limetester PRIVATE ${BCToolbox_tester_TARGET} ${BelleSIP_TARGET} lime ${Soci_TARGET} ${Soci_sqlite3_TARGET} ${CMAKE_THREAD_LIBS_INIT}) + if(ENABLE_PQCRYPTO) + target_link_libraries(limetester PRIVATE ${PostQuantumCryptoEngine_TARGET}) + endif() if(IOS) target_link_libraries(limetester PRIVATE sqlite3) set(MIN_OS ${LINPHONE_IOS_DEPLOYMENT_TARGET}) @@ -78,6 +81,9 @@ else() add_executable(lime-tester ${SOURCE_FILES_CXX} ${HEADER_FILES_CXX} ${SOURCE_FILES_C} ) set_target_properties(lime-tester PROPERTIES LINKER_LANGUAGE CXX) target_link_libraries(lime-tester PRIVATE ${BCToolbox_tester_TARGET} ${BelleSIP_TARGET} lime ${Soci_TARGET} ${Soci_sqlite3_TARGET} ${CMAKE_THREAD_LIBS_INIT}) + if(ENABLE_PQCRYPTO) + target_link_libraries(lime-tester PRIVATE ${PostQuantumCryptoEngine_TARGET}) + endif() # Some tests suite need a local X3DH server running in default config, so run them suite by suite to at least be able to pass some if no server can be found add_test(NAME crypto COMMAND lime-tester --verbose --resource-dir ${CMAKE_CURRENT_SOURCE_DIR} --suite "Crypto") diff --git a/tester/KEM_patterns.cpp b/tester/KEM_patterns.cpp index 03dd8fc..108b107 100644 --- a/tester/KEM_patterns.cpp +++ b/tester/KEM_patterns.cpp @@ -7,11 +7,11 @@ std::vector<uint8_t> sk_KYBER512 = {0x6C, 0x89, 0x2B, 0x02, 0x97, 0xA9, 0xC7, 0x std::vector<uint8_t> pk_KYBER512 = {0x11, 0x5A, 0xCE, 0x0E, 0x64, 0x67, 0x7C, 0xBB, 0x7D, 0xCF, 0xC9, 0x3C, 0x16, 0xD3, 0xA3, 0x05, 0xF6, 0x76, 0x15, 0xA4, 0x88, 0xD7, 0x11, 0xAA, 0x56, 0x69, 0x8C, 0x56, 0x63, 0xAB, 0x7A, 0xC9, 0xCE, 0x66, 0xD5, 0x47, 0xC0, 0x59, 0x5F, 0x98, 0xA4, 0x3F, 0x46, 0x50, 0xBB, 0xE0, 0x8C, 0x36, 0x4D, 0x97, 0x67, 0x89, 0x11, 0x7D, 0x34, 0xF6, 0xAE, 0x51, 0xAC, 0x06, 0x3C, 0xB5, 0x5C, 0x6C, 0xA3, 0x25, 0x58, 0x22, 0x7D, 0xFE, 0xF8, 0x07, 0xD1, 0x9C, 0x30, 0xDE, 0x41, 0x44, 0x24, 0x09, 0x7F, 0x6A, 0xA2, 0x36, 0xA1, 0x05, 0x3B, 0x4A, 0x07, 0xA7, 0x6B, 0xE3, 0x72, 0xA5, 0xC6, 0xB6, 0x00, 0x27, 0x91, 0xEB, 0xE0, 0xAF, 0xDA, 0xF5, 0x4E, 0x1C, 0xA2, 0x37, 0xFF, 0x54, 0x5B, 0xA6, 0x83, 0x43, 0xE7, 0x45, 0xC0, 0x4A, 0xD1, 0x63, 0x9D, 0xBC, 0x59, 0x03, 0x46, 0xB6, 0xB9, 0x56, 0x9B, 0x56, 0xDB, 0xBF, 0xE5, 0x31, 0x51, 0x91, 0x30, 0x66, 0xE5, 0xC8, 0x55, 0x27, 0xDC, 0x94, 0x68, 0x11, 0x0A, 0x13, 0x6A, 0x41, 0x14, 0x97, 0xC2, 0x27, 0xDC, 0xB8, 0xC9, 0xB2, 0x55, 0x70, 0xB7, 0xA0, 0xE4, 0x2A, 0xAD, 0xA6, 0x70, 0x9F, 0x23, 0x20, 0x8F, 0x5D, 0x49, 0x6E, 0xBA, 0xB7, 0x84, 0x3F, 0x64, 0x83, 0xBF, 0x0C, 0x0C, 0x73, 0xA4, 0x02, 0x96, 0xEC, 0x2C, 0x64, 0x40, 0x00, 0x13, 0x94, 0xC9, 0x9C, 0xA1, 0x73, 0xD5, 0xC7, 0x75, 0xB7, 0xF4, 0x15, 0xD0, 0x2A, 0x5A, 0x26, 0xA0, 0x74, 0x07, 0x91, 0x85, 0x87, 0xC4, 0x11, 0x69, 0xF2, 0xB7, 0x17, 0x87, 0x55, 0xAC, 0xC2, 0x7F, 0xC8, 0xB1, 0x9C, 0x4C, 0x4B, 0x3F, 0xCD, 0x41, 0x05, 0x3F, 0x2C, 0x74, 0xC8, 0xA1, 0x0A, 0x83, 0x21, 0x24, 0x1B, 0x28, 0x02, 0x43, 0x28, 0x75, 0xAE, 0x80, 0x8B, 0x9E, 0xF1, 0x36, 0x5C, 0x7B, 0x8A, 0x52, 0x90, 0x2F, 0x13, 0x17, 0xBA, 0x2F, 0xB0, 0x26, 0x9F, 0x47, 0x93, 0x06, 0x72, 0x10, 0x7B, 0x47, 0x26, 0xFE, 0xF6, 0x45, 0x47, 0x39, 0x4D, 0x33, 0x20, 0xC8, 0xF1, 0x20, 0xB3, 0xC2, 0xF4, 0x72, 0x5B, 0x03, 0x05, 0xFA, 0xB8, 0x8C, 0xC7, 0x98, 0x1F, 0xCB, 0x09, 0xA7, 0x6A, 0x1C, 0xBF, 0x7F, 0x17, 0x9F, 0x43, 0xBB, 0x0A, 0x4C, 0x8B, 0x05, 0x90, 0x85, 0x7F, 0x1E, 0x69, 0x70, 0x84, 0x66, 0xC7, 0xF8, 0x60, 0x73, 0x91, 0xE7, 0xBC, 0x52, 0x68, 0xBF, 0xD3, 0xD7, 0xA1, 0xDF, 0xFC, 0xB4, 0xEC, 0xA2, 0xA1, 0xC9, 0xB5, 0x97, 0x59, 0x30, 0x13, 0xD5, 0xFC, 0x42, 0x02, 0xEC, 0x2B, 0x74, 0xE5, 0x7A, 0xB7, 0x6B, 0xBC, 0xF3, 0x63, 0x2B, 0xBA, 0xF9, 0x7C, 0xDC, 0x41, 0x8A, 0x6F, 0x16, 0x39, 0x28, 0x38, 0xCA, 0x9B, 0xF4, 0x5D, 0xDF, 0x02, 0x37, 0x77, 0xB7, 0x56, 0x18, 0x33, 0xC1, 0x05, 0x19, 0x0F, 0x94, 0xF3, 0x02, 0xC5, 0x9B, 0x53, 0x19, 0x00, 0xBB, 0xC8, 0x16, 0x36, 0x1F, 0xAA, 0x5B, 0x33, 0x80, 0xCA, 0x3A, 0x89, 0x31, 0x04, 0xCA, 0x73, 0x88, 0xB1, 0x85, 0x67, 0x1B, 0x3E, 0x5F, 0xE3, 0x79, 0x0E, 0x9A, 0x62, 0x6E, 0xC4, 0x6D, 0x9B, 0x0B, 0x33, 0xC7, 0xA4, 0x19, 0xAF, 0x7B, 0x32, 0xB6, 0x85, 0x98, 0x94, 0xF5, 0x75, 0xD8, 0x2A, 0xC5, 0x45, 0x6B, 0x54, 0x90, 0xA7, 0xAF, 0x8F, 0xE6, 0x10, 0x46, 0x36, 0x05, 0x89, 0xEC, 0xBA, 0x72, 0x44, 0x23, 0x6F, 0x41, 0x23, 0x11, 0x6B, 0x61, 0x74, 0xAA, 0x17, 0x92, 0x49, 0xA4, 0x91, 0x95, 0xB3, 0x56, 0xC7, 0x2F, 0xC6, 0x64, 0x1F, 0x02, 0x51, 0x81, 0x2E, 0xAA, 0x98, 0x57, 0x0B, 0x04, 0x66, 0x99, 0x07, 0x0E, 0x08, 0x19, 0xDC, 0x27, 0x13, 0xF4, 0x69, 0x13, 0x7D, 0xFC, 0x6A, 0x3D, 0x7B, 0x92, 0xB2, 0x98, 0x99, 0x5E, 0xE7, 0x80, 0x36, 0x91, 0x53, 0xAC, 0x36, 0x6B, 0x06, 0xD7, 0x24, 0x9C, 0xD0, 0x9E, 0x1B, 0x33, 0x78, 0xFB, 0x04, 0x39, 0x9C, 0xEC, 0xB8, 0x65, 0x05, 0x81, 0xD6, 0x37, 0xC7, 0x9A, 0xE6, 0x7D, 0x6F, 0x2C, 0xAF, 0x6A, 0xBA, 0xCF, 0x59, 0x81, 0x59, 0xA7, 0x79, 0x2C, 0xB3, 0xC9, 0x71, 0xD1, 0x49, 0x9D, 0x23, 0x73, 0xAD, 0x20, 0xF6, 0x3F, 0x03, 0xBB, 0x59, 0xED, 0x13, 0x73, 0x84, 0xAC, 0x61, 0xA7, 0x15, 0x51, 0x43, 0xB8, 0xCA, 0x49, 0x32, 0x61, 0x2E, 0xC9, 0x15, 0xE4, 0xCA, 0x34, 0x6A, 0x9B, 0xCE, 0x5D, 0xD6, 0x04, 0x17, 0xC6, 0xB2, 0xA8, 0x9B, 0x1C, 0xC4, 0x35, 0x64, 0x3F, 0x87, 0x5B, 0xDC, 0x5A, 0x7E, 0x5B, 0x34, 0x81, 0xCF, 0x91, 0x9E, 0xA0, 0x91, 0x72, 0xFE, 0xBC, 0x46, 0xD4, 0xFC, 0x3F, 0xB0, 0xCB, 0x95, 0x91, 0x70, 0x4E, 0xE2, 0xDB, 0xB6, 0x18, 0x44, 0xB2, 0xF3, 0x31, 0x4A, 0x06, 0xBB, 0x6C, 0x6D, 0x34, 0x00, 0x5E, 0x48, 0x5C, 0xE6, 0x67, 0xBD, 0xC7, 0xD0, 0x98, 0x58, 0x69, 0x28, 0xD2, 0xD9, 0x13, 0x40, 0xF0, 0x04, 0x19, 0xEA, 0x40, 0x13, 0x51, 0xA2, 0x40, 0xA0, 0xB0, 0x41, 0x05, 0x8B, 0xEF, 0xB0, 0xC2, 0xFD, 0x32, 0x64, 0x5B, 0x7A, 0x2D, 0xF8, 0xF5, 0xCB, 0xFD, 0x87, 0x33, 0x27, 0xC9, 0x78, 0xD7, 0xB3, 0x51, 0xA2, 0x80, 0x88, 0x43, 0x88, 0x37, 0x02, 0x4C, 0x52, 0xB9, 0xC2, 0x95, 0xCD, 0x71, 0x36, 0x46, 0xFB, 0x5D, 0x6C, 0x0C, 0xCF, 0xB4, 0x70, 0x73, 0x4A, 0xC2, 0xB2, 0xBC, 0x81, 0x23, 0xC2, 0xC1, 0x3D, 0xF6, 0x93, 0x8E, 0x92, 0x45, 0x5A, 0x86, 0x26, 0x39, 0xFE, 0xB8, 0xA6, 0x4B, 0x85, 0x16, 0x3E, 0x32, 0x70, 0x7E, 0x03, 0x7B, 0x38, 0xD8, 0xAC, 0x39, 0x22, 0xB4, 0x51, 0x87, 0xBB, 0x65, 0xEA, 0xFD, 0x46, 0x5F, 0xC6, 0x4A, 0x0C, 0x5F, 0x8F, 0x3F, 0x90, 0x03, 0x48, 0x94, 0x15, 0x89, 0x9D, 0x59, 0xA5, 0x43, 0xD8, 0x20, 0x8C, 0x54, 0xA3, 0x16, 0x65, 0x29, 0xB5, 0x39, 0x22}; std::vector<uint8_t> ct_KYBER512 = {0xED, 0xF2, 0x41, 0x45, 0xE4, 0x3B, 0x4F, 0x6D, 0xC6, 0xBF, 0x83, 0x32, 0xF5, 0x4E, 0x02, 0xCA, 0xB0, 0x2D, 0xBF, 0x3B, 0x56, 0x05, 0xDD, 0xC9, 0x0A, 0x15, 0xC8, 0x86, 0xAD, 0x3E, 0xD4, 0x89, 0x46, 0x26, 0x99, 0xE4, 0xAB, 0xED, 0x44, 0x35, 0x0B, 0xC3, 0x75, 0x7E, 0x26, 0x96, 0xFB, 0xFB, 0x25, 0x34, 0x41, 0x2E, 0x8D, 0xD2, 0x01, 0xF1, 0xE4, 0x54, 0x0A, 0x39, 0x70, 0xB0, 0x55, 0xFE, 0x3B, 0x0B, 0xEC, 0x3A, 0x71, 0xF9, 0xE1, 0x15, 0xB3, 0xF9, 0xF3, 0x91, 0x02, 0x06, 0x5B, 0x1C, 0xCA, 0x83, 0x14, 0xDC, 0xC7, 0x95, 0xE3, 0xC0, 0xE8, 0xFA, 0x98, 0xEE, 0x83, 0xCA, 0x66, 0x28, 0x45, 0x70, 0x28, 0xA4, 0xD0, 0x9E, 0x83, 0x9E, 0x55, 0x48, 0x62, 0xCF, 0x0B, 0x7B, 0xF5, 0x6C, 0x5C, 0x0A, 0x82, 0x9E, 0x86, 0x57, 0x94, 0x79, 0x45, 0xFE, 0x9C, 0x22, 0x56, 0x4F, 0xBA, 0xEB, 0xC1, 0xB3, 0xAF, 0x35, 0x0D, 0x79, 0x55, 0x50, 0x8A, 0x26, 0xD8, 0xA8, 0xEB, 0x54, 0x7B, 0x8B, 0x1A, 0x2C, 0xF0, 0x3C, 0xCA, 0x1A, 0xAB, 0xCE, 0x6C, 0x34, 0x97, 0x78, 0x3B, 0x64, 0x65, 0xBA, 0x0B, 0x6E, 0x7A, 0xCB, 0xA8, 0x21, 0x19, 0x51, 0x24, 0xAE, 0xF0, 0x9E, 0x62, 0x83, 0x82, 0xA1, 0xF9, 0x14, 0x04, 0x3B, 0xE7, 0x09, 0x6E, 0x95, 0x2C, 0xBC, 0x4F, 0xB4, 0xAF, 0xED, 0x13, 0x60, 0x90, 0x46, 0x11, 0x7C, 0x01, 0x1F, 0xD7, 0x41, 0xEE, 0x28, 0x6C, 0x83, 0x77, 0x16, 0x90, 0xF0, 0xAE, 0xB5, 0x0D, 0xA0, 0xD7, 0x12, 0x85, 0xA1, 0x79, 0xB2, 0x15, 0xC6, 0x03, 0x6D, 0xEB, 0x78, 0x0F, 0x4D, 0x16, 0x76, 0x9F, 0x72, 0xDE, 0x16, 0xFD, 0xAD, 0xAC, 0x73, 0xBE, 0xFA, 0x5B, 0xEF, 0x89, 0x43, 0x19, 0x7F, 0x44, 0xC5, 0x95, 0x89, 0xDC, 0x9F, 0x49, 0x73, 0xDE, 0x14, 0x50, 0xBA, 0x1D, 0x0C, 0x32, 0x90, 0xD6, 0xB1, 0xD6, 0x83, 0xF2, 0x94, 0xE7, 0x59, 0xC9, 0x54, 0xAB, 0xE8, 0xA7, 0xDA, 0x5B, 0x10, 0x54, 0xFD, 0x6D, 0x21, 0x32, 0x9B, 0x8E, 0x73, 0xD3, 0x75, 0x6A, 0xFD, 0xA0, 0xDC, 0xB1, 0xFC, 0x8B, 0x15, 0x82, 0xD1, 0xF9, 0x0C, 0xF2, 0x75, 0xA1, 0x02, 0xAB, 0xC6, 0xAC, 0x69, 0x9D, 0xF0, 0xC5, 0x87, 0x0E, 0x50, 0xA1, 0xF9, 0x89, 0xE4, 0xE6, 0x24, 0x1B, 0x60, 0xAA, 0xA2, 0xEC, 0xF9, 0xE8, 0xE3, 0x3E, 0x0F, 0xFC, 0xF4, 0x0F, 0xE8, 0x31, 0xE8, 0xFD, 0xC2, 0xE8, 0x3B, 0x52, 0xCA, 0x7A, 0xB6, 0xD9, 0x3F, 0x14, 0x6D, 0x29, 0xDC, 0xA5, 0x3C, 0x7D, 0xA1, 0xDB, 0x4A, 0xC4, 0xF2, 0xDB, 0x39, 0xEA, 0x12, 0x0D, 0x90, 0xFA, 0x60, 0xF4, 0xD4, 0x37, 0xC6, 0xD0, 0x0E, 0xF4, 0x83, 0xBC, 0x94, 0xA3, 0x17, 0x5C, 0xDA, 0x16, 0x3F, 0xC1, 0xC2, 0x82, 0x8B, 0xE4, 0xDB, 0xD6, 0x43, 0x05, 0x07, 0xB5, 0x84, 0xBB, 0x51, 0x77, 0xE1, 0x71, 0xB8, 0xDD, 0xA9, 0xA4, 0x29, 0x3C, 0x32, 0x00, 0x29, 0x5C, 0x80, 0x3A, 0x86, 0x5D, 0x6D, 0x21, 0x66, 0xF6, 0x6B, 0xA5, 0x40, 0x1F, 0xB7, 0xA0, 0xE8, 0x53, 0x16, 0x86, 0x00, 0xA2, 0x94, 0x84, 0x37, 0xE0, 0x36, 0xE3, 0xBF, 0x19, 0xE1, 0x2F, 0xD3, 0xF2, 0xA2, 0xB8, 0xB3, 0x43, 0xF7, 0x84, 0x24, 0x8E, 0x8D, 0x68, 0x5E, 0xB0, 0xAF, 0xDE, 0x63, 0x15, 0x33, 0x87, 0x30, 0xE7, 0xA1, 0x00, 0x1C, 0x27, 0xD8, 0xD2, 0xA7, 0x6F, 0xA6, 0x9D, 0x15, 0x7B, 0xA1, 0xAC, 0x7A, 0xD5, 0x6D, 0xA5, 0xA8, 0xC7, 0x0F, 0xE4, 0xB5, 0xB8, 0xD7, 0x86, 0xDC, 0x6F, 0xC0, 0x56, 0x6B, 0xA8, 0xE1, 0xB8, 0x81, 0x63, 0x34, 0xD3, 0x2A, 0x3F, 0xB1, 0xCE, 0x7D, 0x4D, 0x5E, 0x4C, 0x33, 0x2A, 0xF7, 0xB0, 0x03, 0xD0, 0x91, 0x74, 0x1A, 0x3D, 0x5C, 0x96, 0x52, 0x92, 0x25, 0x5D, 0xFF, 0x8E, 0xD2, 0xBB, 0xF1, 0xF9, 0x11, 0x6B, 0xE5, 0x0C, 0x17, 0xB8, 0xE5, 0x48, 0x74, 0x8A, 0xD4, 0xB2, 0xE9, 0x57, 0xBB, 0xD1, 0x95, 0x34, 0x82, 0xA2, 0xE1, 0x71, 0x8C, 0xEC, 0x66, 0xCD, 0x2C, 0x81, 0xF5, 0x72, 0xD5, 0x52, 0xB7, 0x18, 0x78, 0x85, 0xE6, 0xB8, 0x94, 0x3D, 0x64, 0x31, 0x41, 0x3C, 0x59, 0xEB, 0xB7, 0xE0, 0x36, 0x04, 0x84, 0x90, 0xBE, 0x52, 0x89, 0xE9, 0x5B, 0x20, 0xA8, 0x9E, 0x8B, 0x15, 0x9F, 0x61, 0xA9, 0xA9, 0x88, 0x6E, 0x14, 0x75, 0x68, 0xF4, 0xC9, 0x02, 0x1F, 0x36, 0x2F, 0x02, 0x68, 0x8A, 0x1C, 0x8C, 0x3B, 0xB0, 0xD2, 0x40, 0x86, 0x88, 0x0E, 0x55, 0xB6, 0xED, 0xB4, 0x3F, 0x37, 0x45, 0xD2, 0xC1, 0x66, 0xDC, 0x1C, 0xB7, 0x43, 0xC7, 0x6F, 0xE6, 0xBE, 0x52, 0x3A, 0x89, 0x3C, 0xC7, 0x64, 0xD1, 0x64, 0x35, 0xC3, 0x78, 0x51, 0x25, 0x2A, 0x81, 0xE2, 0xFF, 0xBA, 0x0F, 0x18, 0x97, 0x1A, 0x3D, 0xEE, 0x37, 0xD4, 0x87, 0x7C, 0xB9, 0x28, 0xE3, 0x6E, 0x52, 0x35, 0x03, 0x7A, 0x6B, 0x20, 0x57, 0x89, 0x7D, 0x51, 0x8A, 0x5F, 0x0E, 0x34, 0x8E, 0x3A, 0xB6, 0xD5, 0xB5, 0x2D, 0xFC, 0x60, 0x75, 0x7F, 0x3B, 0x41, 0xA4, 0xFE, 0xC7, 0x82, 0x8F, 0x1D, 0xEE, 0xAF, 0x45, 0x87, 0xCC, 0xC8, 0xEA, 0xDF, 0x64, 0x7F, 0x4D, 0x20, 0x3B, 0x2F, 0xAA, 0x05, 0xA6, 0x49, 0xB5, 0x82, 0x34, 0x0C, 0xB4, 0xCA, 0xCE, 0x57, 0xA3, 0x07, 0x11, 0xBE, 0x75, 0x2F, 0xAC, 0xF0, 0x22, 0x7D, 0x0A, 0x80, 0xC4, 0x12, 0x84, 0x42, 0xDD, 0xC5, 0x44, 0xBE, 0x80, 0x5B, 0x9C, 0xFE, 0x8F, 0xE9, 0xB1, 0x23, 0x7C, 0x80, 0xF9, 0x67, 0x87, 0xCD, 0x92, 0x81, 0xCC, 0xF2, 0x70, 0xC1, 0xAF, 0xC0, 0x67, 0x0D}; std::vector<uint8_t> ss_KYBER512 = {0x0A, 0x69, 0x25, 0x67, 0x6F, 0x24, 0xB2, 0x2C, 0x28, 0x6F, 0x4C, 0x81, 0xA4, 0x22, 0x4C, 0xEC, 0x50, 0x6C, 0x9B, 0x25, 0x7D, 0x48, 0x0E, 0x02, 0xE3, 0xB4, 0x9F, 0x44, 0xCA, 0xA3, 0x23, 0x7F}; -std::vector<std::vector<uint8_t>> KYBER512_pattern = {sk_KYBER512, ct_KYBER512, ss_KYBER512}; -// Test vector KYBER1024 -std::vector<uint8_t> sk_KYBER1024 = {0x07, 0x63, 0x8F, 0xB6, 0x98, 0x68, 0xF3, 0xD3, 0x20, 0xE5, 0x86, 0x2B, 0xD9, 0x69, 0x33, 0xFE, 0xB3, 0x11, 0xB3, 0x62, 0x09, 0x3C, 0x9B, 0x5D, 0x50, 0x17, 0x0B, 0xCE, 0xD4, 0x3F, 0x1B, 0x53, 0x6D, 0x9A, 0x20, 0x4B, 0xB1, 0xF2, 0x26, 0x95, 0x95, 0x0B, 0xA1, 0xF2, 0xA9, 0xE8, 0xEB, 0x82, 0x8B, 0x28, 0x44, 0x88, 0x76, 0x0B, 0x3F, 0xC8, 0x4F, 0xAB, 0xA0, 0x42, 0x75, 0xD5, 0x62, 0x8E, 0x39, 0xC5, 0xB2, 0x47, 0x13, 0x74, 0x28, 0x3C, 0x50, 0x32, 0x99, 0xC0, 0xAB, 0x49, 0xB6, 0x6B, 0x8B, 0xBB, 0x56, 0xA4, 0x18, 0x66, 0x24, 0xF9, 0x19, 0xA2, 0xBA, 0x59, 0xBB, 0x08, 0xD8, 0x55, 0x18, 0x80, 0xC2, 0xBE, 0xFC, 0x4F, 0x87, 0xF2, 0x5F, 0x59, 0xAB, 0x58, 0x7A, 0x79, 0xC3, 0x27, 0xD7, 0x92, 0xD5, 0x4C, 0x97, 0x4A, 0x69, 0x26, 0x2F, 0xF8, 0xA7, 0x89, 0x38, 0x28, 0x9E, 0x9A, 0x87, 0xB6, 0x88, 0xB0, 0x83, 0xE0, 0x59, 0x5F, 0xE2, 0x18, 0xB6, 0xBB, 0x15, 0x05, 0x94, 0x1C, 0xE2, 0xE8, 0x1A, 0x5A, 0x64, 0xC5, 0xAA, 0xC6, 0x04, 0x17, 0x25, 0x69, 0x85, 0x34, 0x9E, 0xE4, 0x7A, 0x52, 0x42, 0x0A, 0x5F, 0x97, 0x47, 0x7B, 0x72, 0x36, 0xAC, 0x76, 0xBC, 0x70, 0xE8, 0x28, 0x87, 0x29, 0x28, 0x7E, 0xE3, 0xE3, 0x4A, 0x3D, 0xBC, 0x36, 0x83, 0xC0, 0xB7, 0xB1, 0x00, 0x29, 0xFC, 0x20, 0x34, 0x18, 0x53, 0x7E, 0x74, 0x66, 0xBA, 0x63, 0x85, 0xA8, 0xFF, 0x30, 0x1E, 0xE1, 0x27, 0x08, 0xF8, 0x2A, 0xAA, 0x1E, 0x38, 0x0F, 0xC7, 0xA8, 0x8F, 0x8F, 0x20, 0x5A, 0xB7, 0xE8, 0x8D, 0x7E, 0x95, 0x95, 0x2A, 0x55, 0xBA, 0x20, 0xD0, 0x9B, 0x79, 0xA4, 0x71, 0x41, 0xD6, 0x2B, 0xF6, 0xEB, 0x7D, 0xD3, 0x07, 0xB0, 0x8E, 0xCA, 0x13, 0xA5, 0xBC, 0x5F, 0x6B, 0x68, 0x58, 0x1C, 0x68, 0x65, 0xB2, 0x7B, 0xBC, 0xDD, 0xAB, 0x14, 0x2F, 0x4B, 0x2C, 0xBF, 0xF4, 0x88, 0xC8, 0xA2, 0x27, 0x05, 0xFA, 0xA9, 0x8A, 0x2B, 0x9E, 0xEA, 0x35, 0x30, 0xC7, 0x66, 0x62, 0x33, 0x5C, 0xC7, 0xEA, 0x3A, 0x00, 0x77, 0x77, 0x25, 0xEB, 0xCC, 0xCD, 0x2A, 0x46, 0x36, 0xB2, 0xD9, 0x12, 0x2F, 0xF3, 0xAB, 0x77, 0x12, 0x3C, 0xE0, 0x88, 0x3C, 0x19, 0x11, 0x11, 0x5E, 0x50, 0xC9, 0xE8, 0xA9, 0x41, 0x94, 0xE4, 0x8D, 0xD0, 0xD0, 0x9C, 0xFF, 0xB3, 0xAD, 0xCD, 0x2C, 0x1E, 0x92, 0x43, 0x09, 0x03, 0xD0, 0x7A, 0xDB, 0xF0, 0x05, 0x32, 0x03, 0x15, 0x75, 0xAA, 0x7F, 0x9E, 0x7B, 0x5A, 0x1F, 0x33, 0x62, 0xDE, 0xC9, 0x36, 0xD4, 0x04, 0x3C, 0x05, 0xF2, 0x47, 0x6C, 0x07, 0x57, 0x8B, 0xC9, 0xCB, 0xAF, 0x2A, 0xB4, 0xE3, 0x82, 0x72, 0x7A, 0xD4, 0x16, 0x86, 0xA9, 0x6B, 0x25, 0x48, 0x82, 0x0B, 0xB0, 0x3B, 0x32, 0xF1, 0x1B, 0x28, 0x11, 0xAD, 0x62, 0xF4, 0x89, 0xE9, 0x51, 0x63, 0x2A, 0xBA, 0x0D, 0x1D, 0xF8, 0x96, 0x80, 0xCC, 0x8A, 0x8B, 0x53, 0xB4, 0x81, 0xD9, 0x2A, 0x68, 0xD7, 0x0B, 0x4E, 0xA1, 0xC3, 0xA6, 0xA5, 0x61, 0xC0, 0x69, 0x28, 0x82, 0xB5, 0xCA, 0x8C, 0xC9, 0x42, 0xA8, 0xD4, 0x95, 0xAF, 0xCB, 0x06, 0xDE, 0x89, 0x49, 0x8F, 0xB9, 0x35, 0xB7, 0x75, 0x90, 0x8F, 0xE7, 0xA0, 0x3E, 0x32, 0x4D, 0x54, 0xCC, 0x19, 0xD4, 0xE1, 0xAA, 0xBD, 0x35, 0x93, 0xB3, 0x8B, 0x19, 0xEE, 0x13, 0x88, 0xFE, 0x49, 0x2B, 0x43, 0x12, 0x7E, 0x5A, 0x50, 0x42, 0x53, 0x78, 0x6A, 0x0D, 0x69, 0xAD, 0x32, 0x60, 0x1C, 0x28, 0xE2, 0xC8, 0x85, 0x04, 0xA5, 0xBA, 0x59, 0x97, 0x06, 0x02, 0x3A, 0x61, 0x36, 0x3E, 0x17, 0xC6, 0xB9, 0xBB, 0x59, 0xBD, 0xC6, 0x97, 0x45, 0x2C, 0xD0, 0x59, 0x45, 0x19, 0x83, 0xD7, 0x38, 0xCA, 0x3F, 0xD0, 0x34, 0xE3, 0xF5, 0x98, 0x88, 0x54, 0xCA, 0x05, 0x03, 0x1D, 0xB0, 0x96, 0x11, 0x49, 0x89, 0x88, 0x19, 0x7C, 0x6B, 0x30, 0xD2, 0x58, 0xDF, 0xE2, 0x62, 0x65, 0x54, 0x1C, 0x89, 0xA4, 0xB3, 0x1D, 0x68, 0x64, 0xE9, 0x38, 0x9B, 0x03, 0xCB, 0x74, 0xF7, 0xEC, 0x43, 0x23, 0xFB, 0x94, 0x21, 0xA4, 0xB9, 0x79, 0x0A, 0x26, 0xD1, 0x7B, 0x03, 0x98, 0xA2, 0x67, 0x67, 0x35, 0x09, 0x09, 0xF8, 0x4D, 0x57, 0xB6, 0x69, 0x4D, 0xF8, 0x30, 0x66, 0x4C, 0xA8, 0xB3, 0xC3, 0xC0, 0x3E, 0xD2, 0xAE, 0x67, 0xB8, 0x90, 0x06, 0x86, 0x8A, 0x68, 0x52, 0x7C, 0xCD, 0x66, 0x64, 0x59, 0xAB, 0x7F, 0x05, 0x66, 0x71, 0x00, 0x0C, 0x61, 0x64, 0xD3, 0xA7, 0xF2, 0x66, 0xA1, 0x4D, 0x97, 0xCB, 0xD7, 0x00, 0x4D, 0x6C, 0x92, 0xCA, 0xCA, 0x77, 0x0B, 0x84, 0x4A, 0x4F, 0xA9, 0xB1, 0x82, 0xE7, 0xB1, 0x8C, 0xA8, 0x85, 0x08, 0x2A, 0xC5, 0x64, 0x6F, 0xCB, 0x4A, 0x14, 0xE1, 0x68, 0x5F, 0xEB, 0x0C, 0x9C, 0xE3, 0x37, 0x2A, 0xB9, 0x53, 0x65, 0xC0, 0x4F, 0xD8, 0x30, 0x84, 0xF8, 0x0A, 0x23, 0xFF, 0x10, 0xA0, 0x5B, 0xF1, 0x5F, 0x7F, 0xA5, 0xAC, 0xC6, 0xC0, 0xCB, 0x46, 0x2C, 0x33, 0xCA, 0x52, 0x4F, 0xA6, 0xB8, 0xBB, 0x35, 0x90, 0x43, 0xBA, 0x68, 0x60, 0x9E, 0xAA, 0x25, 0x36, 0xE8, 0x1D, 0x08, 0x46, 0x3B, 0x19, 0x65, 0x3B, 0x54, 0x35, 0xBA, 0x94, 0x6C, 0x9A, 0xDD, 0xEB, 0x20, 0x2B, 0x04, 0xB0, 0x31, 0xCC, 0x96, 0x0D, 0xCC, 0x12, 0xE4, 0x51, 0x8D, 0x42, 0x8B, 0x32, 0xB2, 0x57, 0xA4, 0xFC, 0x73, 0x13, 0xD3, 0xA7, 0x98, 0x0D, 0x80, 0x08, 0x2E, 0x93, 0x4F, 0x9D, 0x95, 0xC3, 0x2B, 0x0A, 0x01, 0x91, 0xA2, 0x36, 0x04, 0x38, 0x4D, 0xD9, 0xE0, 0x79, 0xBB, 0xBA, 0xA2, 0x66, 0xD1, 0x4C, 0x3F, 0x75, 0x6B, 0x9F, 0x21, 0x33, 0x10, 0x74, 0x33, 0xA4, 0xE8, 0x3F, 0xA7, 0x18, 0x72, 0x82, 0xA8, 0x09, 0x20, 0x3A, 0x4F, 0xAF, 0x84, 0x18, 0x51, 0x83, 0x3D, 0x12, 0x1A, 0xC3, 0x83, 0x84, 0x3A, 0x5E, 0x55, 0xBC, 0x23, 0x81, 0x42, 0x5E, 0x16, 0xC7, 0xDB, 0x4C, 0xC9, 0xAB, 0x5C, 0x1B, 0x0D, 0x91, 0xA4, 0x7E, 0x2B, 0x8D, 0xE0, 0xE5, 0x82, 0xC8, 0x6B, 0x6B, 0x0D, 0x90, 0x7B, 0xB3, 0x60, 0xB9, 0x7F, 0x40, 0xAB, 0x5D, 0x03, 0x8F, 0x6B, 0x75, 0xC8, 0x14, 0xB2, 0x7D, 0x9B, 0x96, 0x8D, 0x41, 0x98, 0x32, 0xBC, 0x8C, 0x2B, 0xEE, 0x60, 0x5E, 0xF6, 0xE5, 0x05, 0x9D, 0x33, 0x10, 0x0D, 0x90, 0x48, 0x5D, 0x37, 0x84, 0x50, 0x01, 0x42, 0x21, 0x73, 0x6C, 0x07, 0x40, 0x7C, 0xAC, 0x26, 0x04, 0x08, 0xAA, 0x64, 0x92, 0x66, 0x19, 0x78, 0x8B, 0x86, 0x01, 0xC2, 0xA7, 0x52, 0xD1, 0xA6, 0xCB, 0xF8, 0x20, 0xD7, 0xC7, 0xA0, 0x47, 0x16, 0x20, 0x32, 0x25, 0xB3, 0x89, 0x5B, 0x93, 0x42, 0xD1, 0x47, 0xA8, 0x18, 0x5C, 0xFC, 0x1B, 0xB6, 0x5B, 0xA0, 0x6B, 0x41, 0x42, 0x33, 0x99, 0x03, 0xC0, 0xAC, 0x46, 0x51, 0x38, 0x5B, 0x45, 0xD9, 0x8A, 0x8B, 0x19, 0xD2, 0x8C, 0xD6, 0xBA, 0xB0, 0x88, 0x78, 0x7F, 0x7E, 0xE1, 0xB1, 0x24, 0x61, 0x76, 0x6B, 0x43, 0xCB, 0xCC, 0xB9, 0x64, 0x34, 0x42, 0x7D, 0x93, 0xC0, 0x65, 0x55, 0x06, 0x88, 0xF6, 0x94, 0x8E, 0xD1, 0xB5, 0x47, 0x5A, 0x42, 0x5F, 0x1B, 0x85, 0x20, 0x9D, 0x06, 0x1C, 0x08, 0xB5, 0x6C, 0x1C, 0xC0, 0x69, 0xF6, 0xC0, 0xA7, 0xC6, 0xF2, 0x93, 0x58, 0xCA, 0xB9, 0x11, 0x08, 0x77, 0x32, 0xA6, 0x49, 0xD2, 0x7C, 0x9B, 0x98, 0xF9, 0xA4, 0x88, 0x79, 0x38, 0x7D, 0x9B, 0x00, 0xC2, 0x59, 0x59, 0xA7, 0x16, 0x54, 0xD6, 0xF6, 0xA9, 0x46, 0x16, 0x45, 0x13, 0xE4, 0x7A, 0x75, 0xD0, 0x05, 0x98, 0x6C, 0x23, 0x63, 0xC0, 0x9F, 0x6B, 0x53, 0x7E, 0xCA, 0x78, 0xB9, 0x30, 0x3A, 0x5F, 0xA4, 0x57, 0x60, 0x8A, 0x58, 0x6A, 0x65, 0x3A, 0x34, 0x7D, 0xB0, 0x4D, 0xFC, 0xC1, 0x91, 0x75, 0xB3, 0xA3, 0x01, 0x17, 0x25, 0x36, 0x06, 0x2A, 0x65, 0x8A, 0x95, 0x27, 0x75, 0x70, 0xC8, 0x85, 0x2C, 0xA8, 0x97, 0x3F, 0x4A, 0xE1, 0x23, 0xA3, 0x34, 0x04, 0x7D, 0xD7, 0x11, 0xC8, 0x92, 0x7A, 0x63, 0x4A, 0x03, 0x38, 0x8A, 0x52, 0x7B, 0x03, 0x4B, 0xF7, 0xA8, 0x17, 0x0F, 0xA7, 0x02, 0xC1, 0xF7, 0xC2, 0x3E, 0xC3, 0x2D, 0x18, 0xA2, 0x37, 0x48, 0x90, 0xBE, 0x9C, 0x78, 0x7A, 0x94, 0x09, 0xC8, 0x2D, 0x19, 0x2C, 0x4B, 0xB7, 0x05, 0xA2, 0xF9, 0x96, 0xCE, 0x40, 0x5D, 0x85, 0xA4, 0xC1, 0xA1, 0xAB, 0x9B, 0x6A, 0xEB, 0x49, 0xCC, 0xE1, 0xC2, 0xF8, 0xA9, 0x7C, 0x35, 0x16, 0xC7, 0x2A, 0x00, 0xA4, 0x62, 0x63, 0xBA, 0xA6, 0x96, 0xBF, 0x25, 0x72, 0x77, 0x19, 0xC3, 0x21, 0x64, 0x23, 0x61, 0x8F, 0xF3, 0x33, 0x80, 0x93, 0x4A, 0x6C, 0x10, 0x54, 0x5C, 0x4C, 0x5C, 0x51, 0x55, 0xB1, 0x24, 0x86, 0x18, 0x1F, 0xC7, 0xA2, 0x31, 0x98, 0x73, 0x97, 0x8B, 0x6A, 0x2A, 0x67, 0x49, 0x0F, 0x82, 0x56, 0xBD, 0x21, 0x96, 0xFE, 0x17, 0x92, 0xA4, 0xC0, 0x00, 0x77, 0xB8, 0x12, 0xEA, 0xE8, 0xBE, 0xD3, 0x57, 0x24, 0x99, 0x68, 0x4A, 0xB3, 0x37, 0x18, 0x76, 0x76, 0x1E, 0x45, 0x0C, 0x9F, 0x9D, 0x27, 0x68, 0xA3, 0x68, 0x06, 0xD7, 0xAB, 0x20, 0x46, 0xC9, 0x1F, 0x17, 0x59, 0x9E, 0x9A, 0xC5, 0x92, 0x99, 0x08, 0x08, 0xDC, 0xD7, 0xB4, 0xD0, 0x91, 0x90, 0x72, 0xF1, 0x4E, 0xC3, 0x61, 0x77, 0x3B, 0x72, 0x52, 0x44, 0x4C, 0x32, 0x3C, 0x30, 0x83, 0x26, 0xF4, 0xA3, 0x0F, 0x86, 0x80, 0xD2, 0xF7, 0x48, 0xF5, 0x6A, 0x13, 0x2B, 0x82, 0x67, 0x4E, 0xD0, 0x18, 0x46, 0x20, 0xB8, 0x2A, 0xD2, 0xCB, 0x18, 0x2C, 0x97, 0xB4, 0x81, 0x62, 0x66, 0x47, 0x49, 0x12, 0x90, 0xA0, 0x11, 0xCC, 0x73, 0x82, 0x86, 0x85, 0xA8, 0xC3, 0x67, 0xA5, 0xB9, 0xCF, 0x8D, 0x62, 0x1B, 0x0D, 0x5C, 0x1E, 0xFF, 0x03, 0x17, 0x27, 0x58, 0xBD, 0x00, 0x49, 0x78, 0xC2, 0x51, 0xCD, 0x51, 0x34, 0x22, 0x28, 0x98, 0x9C, 0xAE, 0x63, 0x32, 0xAC, 0x48, 0x64, 0x37, 0xCB, 0x5C, 0x57, 0xD4, 0x30, 0x74, 0x62, 0x86, 0x52, 0x53, 0xBE, 0x21, 0x7B, 0x35, 0x15, 0xC7, 0x3D, 0xF4, 0x05, 0xB7, 0xF2, 0x82, 0x17, 0xAD, 0x0B, 0x8C, 0xF6, 0x0C, 0x2F, 0xFF, 0xAA, 0x0A, 0x00, 0x48, 0xB1, 0xFB, 0x4A, 0xCD, 0xCD, 0xC3, 0x8B, 0x52, 0x50, 0xCF, 0xEC, 0x35, 0x6A, 0x6D, 0xE2, 0x6C, 0xFA, 0x7A, 0x58, 0x8F, 0xDC, 0x86, 0xF9, 0x8C, 0x85, 0x4A, 0xC6, 0x4C, 0x7B, 0xFA, 0xA9, 0x6F, 0x5A, 0x32, 0xCC, 0x06, 0x10, 0x93, 0x4B, 0xAA, 0x6A, 0x58, 0x6B, 0x9A, 0x20, 0x54, 0xF1, 0x3B, 0xA2, 0x74, 0x17, 0x4A, 0xA0, 0xD2, 0xB3, 0xA8, 0x1B, 0x96, 0xA9, 0x40, 0x66, 0x6F, 0x78, 0x9B, 0x5A, 0x6B, 0xCD, 0xC0, 0xA6, 0xA0, 0x17, 0x8A, 0x0C, 0x9A, 0x02, 0x57, 0x8A, 0x49, 0x3F, 0x6E, 0xEA, 0x0D, 0x2E, 0x6C, 0x13, 0x95, 0x1C, 0x9F, 0x24, 0x9A, 0x5E, 0x8D, 0xD7, 0x1D, 0xD4, 0x9A, 0x74, 0x2D, 0x45, 0x1F, 0x1A, 0xBB, 0xA1, 0x9A, 0xF8, 0xC5, 0x47, 0x85, 0x5E, 0x0A, 0xFC, 0x72, 0x8E, 0x90, 0xAB, 0xB4, 0x99, 0xC9, 0xBE, 0xEB, 0x76, 0x6F, 0x47, 0x29, 0xCD, 0xA2, 0x22, 0x63, 0xE3, 0x24, 0xD2, 0x23, 0x02, 0xCB, 0xD3, 0x39, 0x9F, 0xAC, 0xC6, 0x30, 0x99, 0x1F, 0xC8, 0xF2, 0x8B, 0xDB, 0x43, 0x54, 0x76, 0x25, 0x41, 0x52, 0x76, 0x78, 0xBC, 0xF6, 0x1F, 0x65, 0xC2, 0x41, 0x14, 0x6C, 0x42, 0x6D, 0x23, 0xB9, 0xBF, 0xAA, 0x6B, 0x7D, 0xF1, 0x8C, 0x97, 0xF2, 0x0C, 0x1B, 0x61, 0x25, 0xBF, 0x87, 0x4B, 0x1D, 0x89, 0x47, 0x58, 0x52, 0xC4, 0x48, 0x21, 0x5D, 0xB0, 0xEB, 0x77, 0x37, 0xF9, 0x14, 0x80, 0xE8, 0xCE, 0xBD, 0x9A, 0x08, 0x71, 0x57, 0x4F, 0x5A, 0xB6, 0x2D, 0x90, 0x20, 0x17, 0x5E, 0xC6, 0x92, 0x7C, 0xA0, 0xB5, 0x4C, 0x09, 0x81, 0x8E, 0x42, 0xCF, 0x92, 0xA3, 0x83, 0x17, 0x24, 0x22, 0xC7, 0xDC, 0x18, 0x31, 0xD6, 0x3B, 0x0C, 0x29, 0x5D, 0xE7, 0x51, 0x59, 0xDB, 0x80, 0x34, 0xE9, 0xE0, 0x7F, 0x7B, 0x0B, 0x91, 0x0C, 0x3C, 0x1E, 0x5F, 0xB6, 0x6B, 0x3D, 0xC5, 0x23, 0xF1, 0xFA, 0x6E, 0xB4, 0x91, 0x0C, 0xB8, 0x9A, 0x6C, 0x17, 0x56, 0x2C, 0x83, 0xAB, 0x4C, 0x18, 0xD0, 0xCD, 0x7E, 0x07, 0x96, 0x59, 0x2A, 0x37, 0x2A, 0xA4, 0x09, 0xB1, 0xC5, 0x57, 0x34, 0x7C, 0xCA, 0xCD, 0xC4, 0x64, 0x4A, 0x11, 0x90, 0x64, 0xD0, 0x6D, 0xD4, 0x74, 0x92, 0x9D, 0x1C, 0x6F, 0xB4, 0xD6, 0x86, 0xE5, 0x49, 0x1C, 0xE4, 0xBC, 0x89, 0xA3, 0x0B, 0xB4, 0xB8, 0xC4, 0x1B, 0xCE, 0x51, 0x57, 0xDF, 0xC1, 0x36, 0x08, 0x23, 0xB1, 0xAB, 0x61, 0x8C, 0x14, 0xB1, 0x0F, 0x98, 0xC2, 0x50, 0x67, 0x39, 0x8E, 0xA7, 0x01, 0x8C, 0x27, 0x8A, 0x4B, 0x3D, 0xF3, 0x13, 0x34, 0xD6, 0x03, 0xB2, 0x04, 0x4E, 0xF1, 0x87, 0xCD, 0x9B, 0xC6, 0xCE, 0x42, 0x72, 0x5B, 0xD9, 0x62, 0xC2, 0x64, 0x98, 0x3E, 0x9E, 0x18, 0x15, 0x5A, 0x8B, 0x9C, 0x47, 0x14, 0x3D, 0x70, 0x46, 0x0A, 0x26, 0xA5, 0x6F, 0xE7, 0x65, 0x8C, 0x1F, 0x15, 0x03, 0x48, 0xC6, 0x08, 0x7E, 0xF7, 0x58, 0xAD, 0x16, 0x78, 0x87, 0x86, 0x0A, 0x00, 0x7A, 0x5F, 0xC3, 0x73, 0x58, 0xD4, 0x3B, 0x5E, 0xBE, 0xE8, 0x20, 0xAC, 0xEA, 0x47, 0x4F, 0x0A, 0xC0, 0x7B, 0x76, 0x80, 0x28, 0x66, 0x19, 0x9C, 0x61, 0x23, 0x1D, 0x5C, 0x74, 0x7C, 0x93, 0x77, 0x4D, 0x2C, 0x1E, 0x0C, 0x1C, 0x67, 0xE6, 0xC8, 0x1B, 0x82, 0x75, 0x21, 0x73, 0xE1, 0x25, 0xBA, 0xF3, 0x9B, 0x4F, 0xD1, 0x9A, 0x4F, 0x45, 0x3D, 0xC5, 0x79, 0x76, 0xB1, 0xD9, 0x7F, 0xE6, 0x99, 0x69, 0x92, 0xBB, 0xB6, 0x5B, 0x7C, 0xB2, 0x5D, 0x07, 0x7B, 0xBA, 0xA6, 0xA1, 0x33, 0x22, 0x89, 0x9A, 0xF6, 0x59, 0xCF, 0x1B, 0x35, 0x58, 0xC1, 0xB5, 0x00, 0x11, 0x54, 0xB6, 0x25, 0x80, 0x9E, 0xD8, 0x9A, 0xEE, 0xBB, 0x89, 0xE6, 0xEA, 0x7D, 0x67, 0xF7, 0x23, 0xD0, 0x45, 0xAB, 0x05, 0x71, 0x5C, 0x42, 0x35, 0x5D, 0xA6, 0xA5, 0xC8, 0xDD, 0x39, 0xC8, 0xAB, 0xE3, 0x03, 0x77, 0x51, 0xA0, 0x1E, 0xD1, 0xC7, 0x37, 0x49, 0x19, 0xF3, 0x12, 0x1B, 0x5A, 0x52, 0xC5, 0x3D, 0x14, 0x87, 0x31, 0x67, 0x69, 0xF8, 0x07, 0x21, 0xDE, 0xEA, 0xAA, 0xD3, 0xC9, 0x0F, 0x76, 0xE7, 0xAE, 0x9E, 0x12, 0xBA, 0x92, 0xB3, 0x2B, 0x5F, 0xD4, 0x57, 0xE3, 0xC7, 0x52, 0xC2, 0x65, 0x0D, 0xFB, 0x88, 0x57, 0x71, 0xCB, 0x77, 0xAC, 0x3C, 0x78, 0x5A, 0x8C, 0x56, 0x2E, 0x6A, 0x1C, 0x63, 0xC2, 0xA5, 0x5E, 0xA4, 0x7C, 0xF8, 0xB9, 0x0E, 0xB8, 0x22, 0x5C, 0x12, 0x3C, 0x34, 0x64, 0x52, 0x56, 0x62, 0x35, 0xB2, 0xF3, 0x18, 0x23, 0xA3, 0x35, 0x21, 0xE0, 0x87, 0x93, 0x7A, 0x34, 0x5D, 0x8D, 0x66, 0x3E, 0xEA, 0xA0, 0x56, 0x58, 0x91, 0x7B, 0xBA, 0xA0, 0x08, 0xC2, 0xE3, 0x35, 0xF8, 0x85, 0x0A, 0x90, 0xA3, 0x26, 0xD0, 0xE6, 0x64, 0x32, 0xF4, 0x4C, 0xEB, 0x82, 0x89, 0xE4, 0xEC, 0xB2, 0xD1, 0x29, 0x58, 0xE9, 0x84, 0x07, 0x2E, 0xCA, 0xCB, 0x88, 0xE1, 0x34, 0x8F, 0xF0, 0xB5, 0x56, 0x54, 0xAC, 0xBA, 0x5B, 0x54, 0x97, 0x1C, 0xBA, 0xEB, 0xA8, 0x8E, 0xC4, 0xB9, 0x1A, 0x94, 0xC3, 0x71, 0x92, 0xFA, 0x98, 0x2B, 0xEC, 0xB9, 0xF3, 0xDA, 0x42, 0x16, 0x03, 0xB6, 0x1A, 0x51, 0xBC, 0x8E, 0x36, 0xCB, 0xD0, 0x53, 0x85, 0x1C, 0x77, 0xB1, 0xB9, 0x26, 0xB1, 0x7A, 0x27, 0x2A, 0xA9, 0x02, 0x32, 0x46, 0xB0, 0x2B, 0x3E, 0xD4, 0x7F, 0x66, 0xA0, 0x0B, 0xD5, 0x68, 0x48, 0x23, 0x63, 0x4E, 0x7C, 0xE5, 0x8C, 0xF8, 0xF3, 0x06, 0xE3, 0x5B, 0x1E, 0x53, 0x22, 0x82, 0x4D, 0x90, 0x48, 0x01, 0xF0, 0xA2, 0xFA, 0x7C, 0x2B, 0xC9, 0xC2, 0x52, 0xB0, 0xA5, 0x6B, 0x7B, 0xA2, 0xAB, 0x0F, 0x63, 0x60, 0x21, 0x74, 0x5A, 0x70, 0xA9, 0xA4, 0x3E, 0x2B, 0x0A, 0x8D, 0x61, 0x59, 0x70, 0xB6, 0x53, 0x09, 0x62, 0x4B, 0x51, 0x84, 0xBC, 0xC3, 0x0B, 0x91, 0x16, 0x79, 0xAE, 0xDD, 0x76, 0x02, 0x5F, 0xE3, 0x90, 0x8F, 0xD6, 0x78, 0x97, 0xB0, 0xCF, 0x4B, 0xE5, 0xA6, 0xF5, 0x41, 0x3D, 0x7D, 0xD9, 0x85, 0x64, 0xB2, 0x3E, 0x42, 0xA9, 0x3E, 0x4A, 0xA8, 0x82, 0x1C, 0xD4, 0x50, 0x54, 0xC6, 0x43, 0xED, 0xC1, 0x15, 0x8D, 0xB6, 0xB3, 0xDE, 0xB1, 0x3F, 0xB5, 0xA5, 0x1E, 0xBD, 0x1A, 0x8A, 0x78, 0xB8, 0x72, 0x25, 0xA7, 0x33, 0x8E, 0x10, 0x11, 0x04, 0xC4, 0xA2, 0x20, 0xD9, 0xBD, 0xED, 0xD4, 0x8C, 0x85, 0xA1, 0xC2, 0xDA, 0xE7, 0x81, 0xA8, 0x0C, 0x40, 0xE1, 0x3B, 0x87, 0xEA, 0xC7, 0x3A, 0x76, 0x42, 0x01, 0xC9, 0xB7, 0x60, 0xCC, 0xFB, 0x1A, 0xE3, 0x92, 0x69, 0x9C, 0x70, 0x39, 0xD2, 0x7C, 0x39, 0x36, 0x2B, 0x27, 0xB8, 0xFC, 0x6F, 0x07, 0xA8, 0xA3, 0xD4, 0x41, 0x0F, 0x15, 0x47, 0xC4, 0x8A, 0x99, 0x97, 0xF6, 0x2C, 0x61, 0x07, 0x44, 0x52, 0xEF, 0x15, 0x15, 0xF8, 0xA6, 0x49, 0xEB, 0xCA, 0x94, 0x37, 0x20, 0x5A, 0x4E, 0x8A, 0x61, 0x60, 0x6B, 0x41, 0xDA, 0xF6, 0x83, 0x4D, 0x67, 0x1F, 0x4D, 0x85, 0x2C, 0x0C, 0x9C, 0x40, 0x96, 0x61, 0x16, 0x48, 0xC6, 0xA3, 0x17, 0x06, 0x78, 0xB1, 0x53, 0x7C, 0xC1, 0x82, 0x8D, 0x93, 0x58, 0x0C, 0x9E, 0x58, 0x49, 0xA9, 0x65, 0x31, 0x75, 0xAC, 0xB7, 0x53, 0xF2, 0xBE, 0x74, 0x37, 0xBE, 0x45, 0xF6, 0xC6, 0x03, 0xE4, 0x85, 0xF2, 0xEC, 0x30, 0x1B, 0xB4, 0x2B, 0x6C, 0x37, 0xC2, 0x25, 0xD7, 0x49, 0x5A, 0x58, 0x4A, 0xE2, 0x31, 0x89, 0x0A, 0xB5, 0xC8, 0xC3, 0x5C, 0x26, 0x8C, 0xF4, 0xBB, 0xB0, 0x21, 0x3C, 0x09, 0x60, 0x19, 0x31, 0x95, 0x61, 0xA8, 0xA6, 0x94, 0x76, 0x37, 0xAA, 0x40, 0xD0, 0x06, 0xB4, 0x15, 0xBB, 0x2C, 0xFA, 0x22, 0x37, 0xE0, 0x89, 0x0B, 0x6A, 0x3B, 0xC1, 0x34, 0xAB, 0xF8, 0xF6, 0x58, 0x5E, 0x10, 0x8D, 0x15, 0x94, 0x0F, 0x91, 0xF4, 0xBF, 0x5B, 0x0C, 0x81, 0x80, 0x55, 0xB2, 0x1D, 0xEA, 0x6E, 0x63, 0xB5, 0x53, 0x98, 0x8C, 0x47, 0xF4, 0xB9, 0x4E, 0x7C, 0xF8, 0x00, 0xA4, 0x93, 0xB4, 0x73, 0x47, 0x05, 0xED, 0xC5, 0x6A, 0x4B, 0x60, 0x21, 0xC6, 0x29, 0x50, 0x06, 0x75, 0x87, 0x68, 0x04, 0xCF, 0x0B, 0x95, 0x1F, 0x03, 0x8A, 0x5C, 0x7F, 0xE5, 0x8E, 0x89, 0x77, 0x4E, 0xF2, 0x99, 0x2F, 0xD7, 0xC6, 0x30, 0x99, 0xD3, 0x52, 0xA7, 0xD2, 0x15, 0x60, 0xB7, 0x88, 0xB4, 0x05, 0x70, 0x98, 0x61, 0x81, 0x7E, 0x59, 0xA9, 0x6B, 0x3A, 0x3A, 0x83, 0xCB, 0xA8, 0x03, 0xB1, 0x69, 0x34, 0x33, 0x10, 0x71, 0x90, 0x5B, 0xBE, 0xC6, 0x53, 0x29, 0x00, 0x15, 0x5D, 0x8A, 0xC8, 0x8C, 0xB3, 0x2E, 0x4E, 0x21, 0xA3, 0xBD, 0x3A, 0x03, 0xFD, 0xEC, 0x32, 0x5A, 0x51, 0xCD, 0x27, 0x73, 0x96, 0x4E, 0x67, 0x84, 0xFC, 0xF1, 0x85, 0x37, 0x37, 0xAA, 0x64, 0xEB, 0x67, 0x56, 0x47, 0x27, 0x27, 0x26, 0x61, 0xAB, 0xF8, 0x43, 0x13, 0xA5, 0x7A, 0x44, 0xB1, 0x23, 0xC6, 0x55, 0x09, 0xCF, 0xB7, 0xA6, 0xF6, 0x64, 0x1C, 0xDC, 0xC3, 0xB5, 0x7F, 0xE6, 0x28, 0xC7, 0xB8, 0x19, 0x2D, 0xB4, 0x4F, 0xFB, 0xF5, 0x79, 0x6A, 0x86, 0x13, 0xB1, 0xFA, 0x12, 0x6F, 0x60, 0x76, 0x88, 0x3C, 0x78, 0x3D, 0xC2, 0x4E, 0x2A, 0x44, 0x64, 0xC4, 0x0B, 0x3A, 0x41, 0xCA, 0x70, 0xAE, 0x87, 0x62, 0x08, 0x66, 0xCF, 0x4F, 0xCB, 0x2B, 0xD2, 0x04, 0xBF, 0x5C, 0x28, 0x38, 0x12, 0xBA, 0x05, 0x6A, 0xC0, 0xC3, 0x45, 0xE3, 0x79, 0xC4, 0xBA, 0x24, 0xD7, 0x50, 0x90, 0x12, 0x79, 0xBB, 0x2F, 0x3A, 0x16, 0xF6, 0x12, 0xBF, 0xAD, 0xB3, 0x57, 0x03, 0x33, 0x2C, 0x7C, 0x13, 0x6F, 0x68, 0xEA, 0xB6, 0x75, 0x5C, 0x66, 0xB6, 0xA4, 0xAD, 0x1A, 0xAB, 0xA7, 0xB7, 0x68, 0xA5, 0x8A, 0xCA, 0xAC, 0xC1, 0x0A, 0x45, 0x9A, 0x1C, 0xC8, 0xEF, 0x29, 0x37, 0x7B, 0xC2, 0x00, 0xE4, 0xD3, 0x15, 0xA3, 0x0A, 0x6B, 0xCC, 0x32, 0x56, 0xF9, 0x73, 0x4D, 0x06, 0xE9, 0x77, 0x9C, 0xAA, 0x54, 0x42, 0xA9, 0xA1, 0x60, 0x69, 0x08, 0x13, 0x77, 0xC7, 0x6E, 0x75, 0x15, 0x43, 0x68, 0x07, 0x2D, 0xC4, 0x46, 0xED, 0x6C, 0x8B, 0x8E, 0x62, 0x2A, 0x21, 0xE3, 0x83, 0xCF, 0x9B, 0xA1, 0xFB, 0x43, 0x4E, 0x2E, 0xCC, 0x81, 0xE7, 0xB7, 0x8C, 0xEE, 0x98, 0x6B, 0x8F, 0xF7, 0x98, 0xAB, 0x18, 0xCF, 0x96, 0x34, 0x54, 0x35, 0x46, 0x28, 0x4E, 0xDA, 0x2A, 0x26, 0xB4, 0x7F, 0x05, 0xB7, 0x35, 0xBC, 0xDB, 0x12, 0x02, 0x22, 0x00, 0x76, 0xDC, 0x8B, 0x4E, 0x4B, 0x9F, 0x85, 0x35, 0x33, 0xC8, 0xF6, 0xC7, 0xFF, 0x38, 0x81, 0x7B, 0xA4, 0x97, 0x12, 0x83, 0x57, 0x85, 0xF1, 0x7F, 0x14, 0xCA, 0x01, 0xD0, 0xC1, 0xC1, 0xE9, 0x88, 0x10, 0xFE, 0x0B, 0x36, 0xE5, 0xB4, 0x27, 0x15, 0x7B, 0x94, 0x18, 0x44, 0x9C, 0xED, 0xD6, 0x41, 0xA4, 0x29, 0x3C, 0x85, 0xC3, 0x27, 0x00, 0x10, 0x2A, 0xCE, 0xC2, 0x2E, 0xBA, 0xD9, 0x8E, 0xD1, 0x60, 0xA5, 0xF0, 0x27, 0xBD, 0x4C, 0xDA, 0x57, 0xF1, 0xF3, 0x72, 0x0A, 0x12, 0xC1, 0x34, 0x65, 0x4D, 0xD5, 0xE7, 0x3F, 0x82, 0x96, 0x76, 0x49, 0x53, 0x90, 0xD0, 0xE7, 0x92, 0x9D, 0x60, 0x34, 0xE9, 0xC5, 0x5F, 0x7D, 0x55, 0xBA, 0x65, 0x8B, 0xC5, 0x87, 0x98, 0x8E, 0x8A, 0xF9, 0x49, 0x60, 0xF6, 0xCF, 0xB8, 0xD5, 0xAF, 0x7A, 0x00, 0x21, 0x53, 0x5A, 0x6E, 0x25, 0xE4, 0x37, 0xD4, 0x9A, 0x78, 0x06, 0x98, 0xBE, 0x22, 0xAC, 0x99, 0x53, 0x94, 0x9F, 0x57, 0x1B, 0x85, 0xA6, 0x85, 0x72, 0x5F, 0x82, 0x07, 0xA2, 0xB0, 0xAE, 0x84, 0x9B, 0x60, 0x1A, 0xB9, 0x1B, 0x15, 0x9B, 0x3D, 0xF4, 0xA1, 0x54, 0xC2, 0x04, 0x1E, 0x77, 0x60, 0x70, 0xAF, 0xC4, 0x29, 0x69, 0x32, 0x23, 0x80, 0x91, 0x7C, 0x97, 0x51, 0x07, 0x99, 0xF3, 0x14, 0x91, 0x31, 0x47, 0x7E, 0x16, 0x66, 0x3D, 0x31, 0x74, 0xC7, 0xC1, 0xCA, 0xEA, 0x78, 0x85, 0x35, 0xC6, 0xC0, 0x05, 0xA6, 0x4F, 0x28, 0x68, 0x63, 0x1B, 0x31, 0xB6, 0x6E, 0x20, 0x5F, 0xD3, 0x8C, 0x1D, 0x84, 0x54, 0x2D, 0x0F, 0x1B, 0x57, 0x8F, 0x58, 0xC9, 0xBF, 0x5A, 0x0F, 0xAE, 0xAB, 0x6A, 0xB6, 0x49, 0x48, 0x93, 0x05, 0x31, 0x65, 0xEA, 0xFD, 0x46, 0x5F, 0xC6, 0x4A, 0x0C, 0x5F, 0x8F, 0x3F, 0x90, 0x03, 0x48, 0x94, 0x15, 0x89, 0x9D, 0x59, 0xA5, 0x43, 0xD8, 0x20, 0x8C, 0x54, 0xA3, 0x16, 0x65, 0x29, 0xB5, 0x39, 0x22, 0x8A, 0x39, 0xE8, 0x7D, 0x53, 0x1F, 0x35, 0x27, 0xC2, 0x07, 0xED, 0xCC, 0x1D, 0xB7, 0xFA, 0xDD, 0xCF, 0x96, 0x28, 0x39, 0x18, 0x79, 0xB3, 0x35, 0xC7, 0x07, 0x83, 0x9A, 0x0D, 0xB0, 0x51, 0xA8, 0x86, 0x26, 0xED, 0x79, 0xD4, 0x51, 0x14, 0x08, 0x00, 0xE0, 0x3B, 0x59, 0xB9, 0x56, 0xF8, 0x21, 0x0E, 0x55, 0x60, 0x67, 0x40, 0x7D, 0x13, 0xDC, 0x90, 0xFA, 0x9E, 0x8B, 0x87, 0x2B, 0xFB, 0x8F}; -std::vector<uint8_t> pk_KYBER1024 = {0xD2, 0x23, 0x02, 0xCB, 0xD3, 0x39, 0x9F, 0xAC, 0xC6, 0x30, 0x99, 0x1F, 0xC8, 0xF2, 0x8B, 0xDB, 0x43, 0x54, 0x76, 0x25, 0x41, 0x52, 0x76, 0x78, 0xBC, 0xF6, 0x1F, 0x65, 0xC2, 0x41, 0x14, 0x6C, 0x42, 0x6D, 0x23, 0xB9, 0xBF, 0xAA, 0x6B, 0x7D, 0xF1, 0x8C, 0x97, 0xF2, 0x0C, 0x1B, 0x61, 0x25, 0xBF, 0x87, 0x4B, 0x1D, 0x89, 0x47, 0x58, 0x52, 0xC4, 0x48, 0x21, 0x5D, 0xB0, 0xEB, 0x77, 0x37, 0xF9, 0x14, 0x80, 0xE8, 0xCE, 0xBD, 0x9A, 0x08, 0x71, 0x57, 0x4F, 0x5A, 0xB6, 0x2D, 0x90, 0x20, 0x17, 0x5E, 0xC6, 0x92, 0x7C, 0xA0, 0xB5, 0x4C, 0x09, 0x81, 0x8E, 0x42, 0xCF, 0x92, 0xA3, 0x83, 0x17, 0x24, 0x22, 0xC7, 0xDC, 0x18, 0x31, 0xD6, 0x3B, 0x0C, 0x29, 0x5D, 0xE7, 0x51, 0x59, 0xDB, 0x80, 0x34, 0xE9, 0xE0, 0x7F, 0x7B, 0x0B, 0x91, 0x0C, 0x3C, 0x1E, 0x5F, 0xB6, 0x6B, 0x3D, 0xC5, 0x23, 0xF1, 0xFA, 0x6E, 0xB4, 0x91, 0x0C, 0xB8, 0x9A, 0x6C, 0x17, 0x56, 0x2C, 0x83, 0xAB, 0x4C, 0x18, 0xD0, 0xCD, 0x7E, 0x07, 0x96, 0x59, 0x2A, 0x37, 0x2A, 0xA4, 0x09, 0xB1, 0xC5, 0x57, 0x34, 0x7C, 0xCA, 0xCD, 0xC4, 0x64, 0x4A, 0x11, 0x90, 0x64, 0xD0, 0x6D, 0xD4, 0x74, 0x92, 0x9D, 0x1C, 0x6F, 0xB4, 0xD6, 0x86, 0xE5, 0x49, 0x1C, 0xE4, 0xBC, 0x89, 0xA3, 0x0B, 0xB4, 0xB8, 0xC4, 0x1B, 0xCE, 0x51, 0x57, 0xDF, 0xC1, 0x36, 0x08, 0x23, 0xB1, 0xAB, 0x61, 0x8C, 0x14, 0xB1, 0x0F, 0x98, 0xC2, 0x50, 0x67, 0x39, 0x8E, 0xA7, 0x01, 0x8C, 0x27, 0x8A, 0x4B, 0x3D, 0xF3, 0x13, 0x34, 0xD6, 0x03, 0xB2, 0x04, 0x4E, 0xF1, 0x87, 0xCD, 0x9B, 0xC6, 0xCE, 0x42, 0x72, 0x5B, 0xD9, 0x62, 0xC2, 0x64, 0x98, 0x3E, 0x9E, 0x18, 0x15, 0x5A, 0x8B, 0x9C, 0x47, 0x14, 0x3D, 0x70, 0x46, 0x0A, 0x26, 0xA5, 0x6F, 0xE7, 0x65, 0x8C, 0x1F, 0x15, 0x03, 0x48, 0xC6, 0x08, 0x7E, 0xF7, 0x58, 0xAD, 0x16, 0x78, 0x87, 0x86, 0x0A, 0x00, 0x7A, 0x5F, 0xC3, 0x73, 0x58, 0xD4, 0x3B, 0x5E, 0xBE, 0xE8, 0x20, 0xAC, 0xEA, 0x47, 0x4F, 0x0A, 0xC0, 0x7B, 0x76, 0x80, 0x28, 0x66, 0x19, 0x9C, 0x61, 0x23, 0x1D, 0x5C, 0x74, 0x7C, 0x93, 0x77, 0x4D, 0x2C, 0x1E, 0x0C, 0x1C, 0x67, 0xE6, 0xC8, 0x1B, 0x82, 0x75, 0x21, 0x73, 0xE1, 0x25, 0xBA, 0xF3, 0x9B, 0x4F, 0xD1, 0x9A, 0x4F, 0x45, 0x3D, 0xC5, 0x79, 0x76, 0xB1, 0xD9, 0x7F, 0xE6, 0x99, 0x69, 0x92, 0xBB, 0xB6, 0x5B, 0x7C, 0xB2, 0x5D, 0x07, 0x7B, 0xBA, 0xA6, 0xA1, 0x33, 0x22, 0x89, 0x9A, 0xF6, 0x59, 0xCF, 0x1B, 0x35, 0x58, 0xC1, 0xB5, 0x00, 0x11, 0x54, 0xB6, 0x25, 0x80, 0x9E, 0xD8, 0x9A, 0xEE, 0xBB, 0x89, 0xE6, 0xEA, 0x7D, 0x67, 0xF7, 0x23, 0xD0, 0x45, 0xAB, 0x05, 0x71, 0x5C, 0x42, 0x35, 0x5D, 0xA6, 0xA5, 0xC8, 0xDD, 0x39, 0xC8, 0xAB, 0xE3, 0x03, 0x77, 0x51, 0xA0, 0x1E, 0xD1, 0xC7, 0x37, 0x49, 0x19, 0xF3, 0x12, 0x1B, 0x5A, 0x52, 0xC5, 0x3D, 0x14, 0x87, 0x31, 0x67, 0x69, 0xF8, 0x07, 0x21, 0xDE, 0xEA, 0xAA, 0xD3, 0xC9, 0x0F, 0x76, 0xE7, 0xAE, 0x9E, 0x12, 0xBA, 0x92, 0xB3, 0x2B, 0x5F, 0xD4, 0x57, 0xE3, 0xC7, 0x52, 0xC2, 0x65, 0x0D, 0xFB, 0x88, 0x57, 0x71, 0xCB, 0x77, 0xAC, 0x3C, 0x78, 0x5A, 0x8C, 0x56, 0x2E, 0x6A, 0x1C, 0x63, 0xC2, 0xA5, 0x5E, 0xA4, 0x7C, 0xF8, 0xB9, 0x0E, 0xB8, 0x22, 0x5C, 0x12, 0x3C, 0x34, 0x64, 0x52, 0x56, 0x62, 0x35, 0xB2, 0xF3, 0x18, 0x23, 0xA3, 0x35, 0x21, 0xE0, 0x87, 0x93, 0x7A, 0x34, 0x5D, 0x8D, 0x66, 0x3E, 0xEA, 0xA0, 0x56, 0x58, 0x91, 0x7B, 0xBA, 0xA0, 0x08, 0xC2, 0xE3, 0x35, 0xF8, 0x85, 0x0A, 0x90, 0xA3, 0x26, 0xD0, 0xE6, 0x64, 0x32, 0xF4, 0x4C, 0xEB, 0x82, 0x89, 0xE4, 0xEC, 0xB2, 0xD1, 0x29, 0x58, 0xE9, 0x84, 0x07, 0x2E, 0xCA, 0xCB, 0x88, 0xE1, 0x34, 0x8F, 0xF0, 0xB5, 0x56, 0x54, 0xAC, 0xBA, 0x5B, 0x54, 0x97, 0x1C, 0xBA, 0xEB, 0xA8, 0x8E, 0xC4, 0xB9, 0x1A, 0x94, 0xC3, 0x71, 0x92, 0xFA, 0x98, 0x2B, 0xEC, 0xB9, 0xF3, 0xDA, 0x42, 0x16, 0x03, 0xB6, 0x1A, 0x51, 0xBC, 0x8E, 0x36, 0xCB, 0xD0, 0x53, 0x85, 0x1C, 0x77, 0xB1, 0xB9, 0x26, 0xB1, 0x7A, 0x27, 0x2A, 0xA9, 0x02, 0x32, 0x46, 0xB0, 0x2B, 0x3E, 0xD4, 0x7F, 0x66, 0xA0, 0x0B, 0xD5, 0x68, 0x48, 0x23, 0x63, 0x4E, 0x7C, 0xE5, 0x8C, 0xF8, 0xF3, 0x06, 0xE3, 0x5B, 0x1E, 0x53, 0x22, 0x82, 0x4D, 0x90, 0x48, 0x01, 0xF0, 0xA2, 0xFA, 0x7C, 0x2B, 0xC9, 0xC2, 0x52, 0xB0, 0xA5, 0x6B, 0x7B, 0xA2, 0xAB, 0x0F, 0x63, 0x60, 0x21, 0x74, 0x5A, 0x70, 0xA9, 0xA4, 0x3E, 0x2B, 0x0A, 0x8D, 0x61, 0x59, 0x70, 0xB6, 0x53, 0x09, 0x62, 0x4B, 0x51, 0x84, 0xBC, 0xC3, 0x0B, 0x91, 0x16, 0x79, 0xAE, 0xDD, 0x76, 0x02, 0x5F, 0xE3, 0x90, 0x8F, 0xD6, 0x78, 0x97, 0xB0, 0xCF, 0x4B, 0xE5, 0xA6, 0xF5, 0x41, 0x3D, 0x7D, 0xD9, 0x85, 0x64, 0xB2, 0x3E, 0x42, 0xA9, 0x3E, 0x4A, 0xA8, 0x82, 0x1C, 0xD4, 0x50, 0x54, 0xC6, 0x43, 0xED, 0xC1, 0x15, 0x8D, 0xB6, 0xB3, 0xDE, 0xB1, 0x3F, 0xB5, 0xA5, 0x1E, 0xBD, 0x1A, 0x8A, 0x78, 0xB8, 0x72, 0x25, 0xA7, 0x33, 0x8E, 0x10, 0x11, 0x04, 0xC4, 0xA2, 0x20, 0xD9, 0xBD, 0xED, 0xD4, 0x8C, 0x85, 0xA1, 0xC2, 0xDA, 0xE7, 0x81, 0xA8, 0x0C, 0x40, 0xE1, 0x3B, 0x87, 0xEA, 0xC7, 0x3A, 0x76, 0x42, 0x01, 0xC9, 0xB7, 0x60, 0xCC, 0xFB, 0x1A, 0xE3, 0x92, 0x69, 0x9C, 0x70, 0x39, 0xD2, 0x7C, 0x39, 0x36, 0x2B, 0x27, 0xB8, 0xFC, 0x6F, 0x07, 0xA8, 0xA3, 0xD4, 0x41, 0x0F, 0x15, 0x47, 0xC4, 0x8A, 0x99, 0x97, 0xF6, 0x2C, 0x61, 0x07, 0x44, 0x52, 0xEF, 0x15, 0x15, 0xF8, 0xA6, 0x49, 0xEB, 0xCA, 0x94, 0x37, 0x20, 0x5A, 0x4E, 0x8A, 0x61, 0x60, 0x6B, 0x41, 0xDA, 0xF6, 0x83, 0x4D, 0x67, 0x1F, 0x4D, 0x85, 0x2C, 0x0C, 0x9C, 0x40, 0x96, 0x61, 0x16, 0x48, 0xC6, 0xA3, 0x17, 0x06, 0x78, 0xB1, 0x53, 0x7C, 0xC1, 0x82, 0x8D, 0x93, 0x58, 0x0C, 0x9E, 0x58, 0x49, 0xA9, 0x65, 0x31, 0x75, 0xAC, 0xB7, 0x53, 0xF2, 0xBE, 0x74, 0x37, 0xBE, 0x45, 0xF6, 0xC6, 0x03, 0xE4, 0x85, 0xF2, 0xEC, 0x30, 0x1B, 0xB4, 0x2B, 0x6C, 0x37, 0xC2, 0x25, 0xD7, 0x49, 0x5A, 0x58, 0x4A, 0xE2, 0x31, 0x89, 0x0A, 0xB5, 0xC8, 0xC3, 0x5C, 0x26, 0x8C, 0xF4, 0xBB, 0xB0, 0x21, 0x3C, 0x09, 0x60, 0x19, 0x31, 0x95, 0x61, 0xA8, 0xA6, 0x94, 0x76, 0x37, 0xAA, 0x40, 0xD0, 0x06, 0xB4, 0x15, 0xBB, 0x2C, 0xFA, 0x22, 0x37, 0xE0, 0x89, 0x0B, 0x6A, 0x3B, 0xC1, 0x34, 0xAB, 0xF8, 0xF6, 0x58, 0x5E, 0x10, 0x8D, 0x15, 0x94, 0x0F, 0x91, 0xF4, 0xBF, 0x5B, 0x0C, 0x81, 0x80, 0x55, 0xB2, 0x1D, 0xEA, 0x6E, 0x63, 0xB5, 0x53, 0x98, 0x8C, 0x47, 0xF4, 0xB9, 0x4E, 0x7C, 0xF8, 0x00, 0xA4, 0x93, 0xB4, 0x73, 0x47, 0x05, 0xED, 0xC5, 0x6A, 0x4B, 0x60, 0x21, 0xC6, 0x29, 0x50, 0x06, 0x75, 0x87, 0x68, 0x04, 0xCF, 0x0B, 0x95, 0x1F, 0x03, 0x8A, 0x5C, 0x7F, 0xE5, 0x8E, 0x89, 0x77, 0x4E, 0xF2, 0x99, 0x2F, 0xD7, 0xC6, 0x30, 0x99, 0xD3, 0x52, 0xA7, 0xD2, 0x15, 0x60, 0xB7, 0x88, 0xB4, 0x05, 0x70, 0x98, 0x61, 0x81, 0x7E, 0x59, 0xA9, 0x6B, 0x3A, 0x3A, 0x83, 0xCB, 0xA8, 0x03, 0xB1, 0x69, 0x34, 0x33, 0x10, 0x71, 0x90, 0x5B, 0xBE, 0xC6, 0x53, 0x29, 0x00, 0x15, 0x5D, 0x8A, 0xC8, 0x8C, 0xB3, 0x2E, 0x4E, 0x21, 0xA3, 0xBD, 0x3A, 0x03, 0xFD, 0xEC, 0x32, 0x5A, 0x51, 0xCD, 0x27, 0x73, 0x96, 0x4E, 0x67, 0x84, 0xFC, 0xF1, 0x85, 0x37, 0x37, 0xAA, 0x64, 0xEB, 0x67, 0x56, 0x47, 0x27, 0x27, 0x26, 0x61, 0xAB, 0xF8, 0x43, 0x13, 0xA5, 0x7A, 0x44, 0xB1, 0x23, 0xC6, 0x55, 0x09, 0xCF, 0xB7, 0xA6, 0xF6, 0x64, 0x1C, 0xDC, 0xC3, 0xB5, 0x7F, 0xE6, 0x28, 0xC7, 0xB8, 0x19, 0x2D, 0xB4, 0x4F, 0xFB, 0xF5, 0x79, 0x6A, 0x86, 0x13, 0xB1, 0xFA, 0x12, 0x6F, 0x60, 0x76, 0x88, 0x3C, 0x78, 0x3D, 0xC2, 0x4E, 0x2A, 0x44, 0x64, 0xC4, 0x0B, 0x3A, 0x41, 0xCA, 0x70, 0xAE, 0x87, 0x62, 0x08, 0x66, 0xCF, 0x4F, 0xCB, 0x2B, 0xD2, 0x04, 0xBF, 0x5C, 0x28, 0x38, 0x12, 0xBA, 0x05, 0x6A, 0xC0, 0xC3, 0x45, 0xE3, 0x79, 0xC4, 0xBA, 0x24, 0xD7, 0x50, 0x90, 0x12, 0x79, 0xBB, 0x2F, 0x3A, 0x16, 0xF6, 0x12, 0xBF, 0xAD, 0xB3, 0x57, 0x03, 0x33, 0x2C, 0x7C, 0x13, 0x6F, 0x68, 0xEA, 0xB6, 0x75, 0x5C, 0x66, 0xB6, 0xA4, 0xAD, 0x1A, 0xAB, 0xA7, 0xB7, 0x68, 0xA5, 0x8A, 0xCA, 0xAC, 0xC1, 0x0A, 0x45, 0x9A, 0x1C, 0xC8, 0xEF, 0x29, 0x37, 0x7B, 0xC2, 0x00, 0xE4, 0xD3, 0x15, 0xA3, 0x0A, 0x6B, 0xCC, 0x32, 0x56, 0xF9, 0x73, 0x4D, 0x06, 0xE9, 0x77, 0x9C, 0xAA, 0x54, 0x42, 0xA9, 0xA1, 0x60, 0x69, 0x08, 0x13, 0x77, 0xC7, 0x6E, 0x75, 0x15, 0x43, 0x68, 0x07, 0x2D, 0xC4, 0x46, 0xED, 0x6C, 0x8B, 0x8E, 0x62, 0x2A, 0x21, 0xE3, 0x83, 0xCF, 0x9B, 0xA1, 0xFB, 0x43, 0x4E, 0x2E, 0xCC, 0x81, 0xE7, 0xB7, 0x8C, 0xEE, 0x98, 0x6B, 0x8F, 0xF7, 0x98, 0xAB, 0x18, 0xCF, 0x96, 0x34, 0x54, 0x35, 0x46, 0x28, 0x4E, 0xDA, 0x2A, 0x26, 0xB4, 0x7F, 0x05, 0xB7, 0x35, 0xBC, 0xDB, 0x12, 0x02, 0x22, 0x00, 0x76, 0xDC, 0x8B, 0x4E, 0x4B, 0x9F, 0x85, 0x35, 0x33, 0xC8, 0xF6, 0xC7, 0xFF, 0x38, 0x81, 0x7B, 0xA4, 0x97, 0x12, 0x83, 0x57, 0x85, 0xF1, 0x7F, 0x14, 0xCA, 0x01, 0xD0, 0xC1, 0xC1, 0xE9, 0x88, 0x10, 0xFE, 0x0B, 0x36, 0xE5, 0xB4, 0x27, 0x15, 0x7B, 0x94, 0x18, 0x44, 0x9C, 0xED, 0xD6, 0x41, 0xA4, 0x29, 0x3C, 0x85, 0xC3, 0x27, 0x00, 0x10, 0x2A, 0xCE, 0xC2, 0x2E, 0xBA, 0xD9, 0x8E, 0xD1, 0x60, 0xA5, 0xF0, 0x27, 0xBD, 0x4C, 0xDA, 0x57, 0xF1, 0xF3, 0x72, 0x0A, 0x12, 0xC1, 0x34, 0x65, 0x4D, 0xD5, 0xE7, 0x3F, 0x82, 0x96, 0x76, 0x49, 0x53, 0x90, 0xD0, 0xE7, 0x92, 0x9D, 0x60, 0x34, 0xE9, 0xC5, 0x5F, 0x7D, 0x55, 0xBA, 0x65, 0x8B, 0xC5, 0x87, 0x98, 0x8E, 0x8A, 0xF9, 0x49, 0x60, 0xF6, 0xCF, 0xB8, 0xD5, 0xAF, 0x7A, 0x00, 0x21, 0x53, 0x5A, 0x6E, 0x25, 0xE4, 0x37, 0xD4, 0x9A, 0x78, 0x06, 0x98, 0xBE, 0x22, 0xAC, 0x99, 0x53, 0x94, 0x9F, 0x57, 0x1B, 0x85, 0xA6, 0x85, 0x72, 0x5F, 0x82, 0x07, 0xA2, 0xB0, 0xAE, 0x84, 0x9B, 0x60, 0x1A, 0xB9, 0x1B, 0x15, 0x9B, 0x3D, 0xF4, 0xA1, 0x54, 0xC2, 0x04, 0x1E, 0x77, 0x60, 0x70, 0xAF, 0xC4, 0x29, 0x69, 0x32, 0x23, 0x80, 0x91, 0x7C, 0x97, 0x51, 0x07, 0x99, 0xF3, 0x14, 0x91, 0x31, 0x47, 0x7E, 0x16, 0x66, 0x3D, 0x31, 0x74, 0xC7, 0xC1, 0xCA, 0xEA, 0x78, 0x85, 0x35, 0xC6, 0xC0, 0x05, 0xA6, 0x4F, 0x28, 0x68, 0x63, 0x1B, 0x31, 0xB6, 0x6E, 0x20, 0x5F, 0xD3, 0x8C, 0x1D, 0x84, 0x54, 0x2D, 0x0F, 0x1B, 0x57, 0x8F, 0x58, 0xC9, 0xBF, 0x5A, 0x0F, 0xAE, 0xAB, 0x6A, 0xB6, 0x49, 0x48, 0x93, 0x05, 0x31, 0x65, 0xEA, 0xFD, 0x46, 0x5F, 0xC6, 0x4A, 0x0C, 0x5F, 0x8F, 0x3F, 0x90, 0x03, 0x48, 0x94, 0x15, 0x89, 0x9D, 0x59, 0xA5, 0x43, 0xD8, 0x20, 0x8C, 0x54, 0xA3, 0x16, 0x65, 0x29, 0xB5, 0x39, 0x22}; -std::vector<uint8_t> ct_KYBER1024 = {0xA6, 0xAF, 0x29, 0xD5, 0xF5, 0xB8, 0x0B, 0xD1, 0x30, 0xF5, 0x18, 0xBA, 0xDD, 0xD6, 0xC8, 0xF1, 0x75, 0x45, 0x41, 0x3D, 0x86, 0x0F, 0xB3, 0xDE, 0x45, 0x19, 0x79, 0xEB, 0xFA, 0x5E, 0x4E, 0x31, 0x12, 0xC7, 0xC0, 0xAD, 0xF9, 0x98, 0x24, 0xBB, 0x52, 0x6F, 0x2C, 0x35, 0x50, 0x74, 0x8E, 0xD0, 0xE1, 0x34, 0xF0, 0x45, 0x7A, 0x7C, 0x61, 0xF9, 0xF5, 0x26, 0xF0, 0x02, 0xBA, 0xAD, 0xC0, 0x3F, 0xC1, 0x3E, 0x38, 0x13, 0x12, 0x19, 0x51, 0x3C, 0x3E, 0xDE, 0x06, 0x16, 0x61, 0xE7, 0x4F, 0x60, 0x3C, 0x4F, 0xCF, 0x79, 0x51, 0xC8, 0xE5, 0x2C, 0x9C, 0x21, 0x3B, 0x0D, 0x22, 0xD9, 0x29, 0x36, 0x63, 0xD6, 0x69, 0xA6, 0xB5, 0x8E, 0xD8, 0xFC, 0xEF, 0xCF, 0x82, 0x49, 0xD7, 0xBB, 0x52, 0x98, 0xF5, 0x57, 0x61, 0x44, 0x5B, 0x2B, 0x83, 0xCE, 0x7F, 0x00, 0x5C, 0xB0, 0x42, 0x48, 0xAE, 0xC8, 0xBD, 0xA2, 0x2F, 0xD2, 0xD4, 0x2A, 0xA7, 0x66, 0x32, 0x20, 0x14, 0xEA, 0x03, 0x8C, 0xC3, 0x2C, 0x55, 0xC8, 0xE4, 0xB9, 0xE2, 0x8E, 0xC9, 0x11, 0x9F, 0x52, 0x73, 0x41, 0xE4, 0xF6, 0x6A, 0x03, 0x51, 0x21, 0x07, 0x3B, 0x85, 0xDE, 0x67, 0x06, 0xDA, 0x19, 0xE0, 0x83, 0x8A, 0x9F, 0x33, 0xB7, 0x19, 0xA6, 0x8F, 0x03, 0x9B, 0x66, 0x4D, 0xC0, 0x02, 0x65, 0x9E, 0xAB, 0xFC, 0x39, 0x86, 0x79, 0xAA, 0x70, 0x09, 0xCE, 0x0C, 0xD0, 0x1C, 0xDA, 0xFB, 0x6C, 0xD2, 0xA2, 0x6F, 0xE4, 0x10, 0x16, 0x72, 0xC9, 0x8F, 0xF5, 0x8F, 0x7C, 0x47, 0xD5, 0xBD, 0xA2, 0x90, 0x66, 0x53, 0xB3, 0xA6, 0xF9, 0x65, 0x1F, 0x7A, 0x12, 0x1E, 0xA7, 0x7E, 0xA7, 0x47, 0x23, 0xFA, 0xE5, 0xB8, 0x73, 0xF9, 0xBB, 0x7B, 0x66, 0x4F, 0x0C, 0x8A, 0x93, 0x83, 0x1E, 0xF9, 0xD5, 0x1C, 0x7C, 0xC1, 0xEF, 0x44, 0xAC, 0x0E, 0x55, 0xA5, 0x5C, 0xA7, 0x6D, 0x13, 0x7F, 0xE9, 0xB7, 0x5F, 0x40, 0x50, 0x9C, 0xEF, 0x15, 0x6E, 0x5A, 0xD1, 0x8F, 0x9F, 0xB9, 0x99, 0x68, 0x00, 0x08, 0xE5, 0x47, 0xD5, 0x5E, 0xEC, 0xD5, 0xB4, 0xD1, 0xCB, 0x1D, 0x9F, 0x07, 0x6C, 0xEC, 0x21, 0x50, 0x1C, 0x74, 0x02, 0x50, 0x9E, 0xCB, 0x77, 0xAF, 0xB2, 0xCB, 0x9A, 0x61, 0x34, 0x0A, 0x8B, 0xD1, 0x51, 0x4C, 0x6E, 0x71, 0xB4, 0xAA, 0x45, 0xE4, 0x7E, 0xC3, 0x75, 0x12, 0x27, 0x1B, 0x91, 0x1F, 0x8F, 0xB4, 0x6C, 0x90, 0x82, 0xC9, 0xDF, 0x07, 0x20, 0x4A, 0xBB, 0x5A, 0x50, 0xE6, 0xE3, 0x64, 0x7A, 0x8A, 0xD4, 0xD8, 0xD5, 0xD7, 0xBF, 0xF1, 0x9C, 0x8A, 0x50, 0x93, 0x08, 0xBC, 0xFB, 0x89, 0x55, 0x36, 0xD0, 0x45, 0xCA, 0x2B, 0x97, 0xCB, 0x16, 0xA2, 0x9B, 0xB7, 0x18, 0x1C, 0xAD, 0x05, 0x09, 0xDD, 0xB9, 0x17, 0x35, 0x02, 0x8E, 0xBA, 0x8C, 0x31, 0xD7, 0x4B, 0xD2, 0x75, 0xEA, 0xA6, 0x5B, 0x53, 0x40, 0xB3, 0xA4, 0x3F, 0xBF, 0xE0, 0xB3, 0x06, 0x1D, 0x6B, 0xAE, 0x7E, 0x75, 0xB7, 0x09, 0x8C, 0xDA, 0xBE, 0x91, 0xD4, 0xB3, 0x1E, 0x36, 0xC9, 0xAA, 0x7A, 0x82, 0x98, 0x86, 0x2A, 0xD6, 0x3C, 0x8F, 0xD2, 0x82, 0xE0, 0x3B, 0x46, 0x0B, 0x3A, 0xB4, 0x64, 0xCE, 0x0F, 0x27, 0xB1, 0xC3, 0xD1, 0x11, 0x55, 0xAC, 0xAA, 0x01, 0x1E, 0xB9, 0xE2, 0xAE, 0x3E, 0x6D, 0xDA, 0x07, 0xD6, 0xF4, 0x91, 0x73, 0x7C, 0xBC, 0xE9, 0xB0, 0x5F, 0x9B, 0xC5, 0x6B, 0xE2, 0x0E, 0x8D, 0x32, 0x6B, 0xA1, 0x32, 0xC5, 0x7F, 0xB2, 0x35, 0x16, 0x11, 0x44, 0x51, 0x9C, 0xDF, 0x40, 0x56, 0x0F, 0xBE, 0x27, 0x9B, 0xDE, 0x41, 0x1E, 0x11, 0x25, 0x31, 0xF8, 0x26, 0xD6, 0xAB, 0x10, 0xD4, 0x54, 0x73, 0x50, 0xAD, 0xD2, 0xA9, 0xDE, 0x8D, 0x62, 0xC2, 0xAC, 0x82, 0xCA, 0xBE, 0x68, 0x15, 0x64, 0x6F, 0x4D, 0xC9, 0x74, 0x2B, 0xB0, 0xC2, 0xA3, 0xF7, 0x7E, 0xC7, 0xB4, 0x6C, 0x6B, 0x53, 0x76, 0x05, 0xFA, 0x31, 0x79, 0x8C, 0xD8, 0x92, 0x81, 0x22, 0x1A, 0x33, 0xDF, 0xB9, 0x79, 0x6E, 0x64, 0x43, 0x05, 0x63, 0x03, 0x32, 0xC2, 0xCB, 0x93, 0x14, 0x08, 0xAB, 0x48, 0x1A, 0x16, 0xD9, 0x53, 0xF6, 0xBE, 0xAE, 0x38, 0x91, 0xD6, 0xD9, 0xAC, 0x1F, 0xAB, 0x38, 0x22, 0x2D, 0x92, 0x71, 0x87, 0x2D, 0x9D, 0x0C, 0xAD, 0xB9, 0x1A, 0xBE, 0x9B, 0x4E, 0x26, 0x5F, 0x75, 0xC6, 0xE5, 0xE8, 0x29, 0xE1, 0x46, 0xC3, 0xD8, 0xCE, 0x1E, 0x9D, 0x12, 0xE0, 0xD1, 0x29, 0x80, 0x19, 0x57, 0xF4, 0x6B, 0x0D, 0x2D, 0xBE, 0x1F, 0x74, 0x9B, 0x1D, 0x08, 0xE2, 0x34, 0x5F, 0x62, 0x39, 0xA7, 0x31, 0x34, 0x2E, 0xB7, 0x5B, 0x0C, 0xF1, 0xBF, 0x41, 0x17, 0x49, 0xBC, 0x2C, 0xAF, 0x28, 0x10, 0xB7, 0x88, 0xC6, 0xB7, 0x23, 0x8B, 0x4D, 0x3D, 0xA2, 0xD6, 0x31, 0x5C, 0xE9, 0x54, 0x2E, 0x24, 0x40, 0x4F, 0x14, 0x57, 0x55, 0xA3, 0x0A, 0xB8, 0x51, 0xE4, 0x44, 0x58, 0x41, 0xBD, 0x33, 0xF7, 0x16, 0xA5, 0x86, 0x88, 0x48, 0x88, 0xEC, 0xC6, 0xBC, 0x64, 0x98, 0xAA, 0x32, 0x91, 0x9A, 0xE8, 0x1D, 0x20, 0xC2, 0x69, 0x73, 0xC2, 0xBD, 0x54, 0x58, 0x2A, 0x0F, 0x6A, 0xD9, 0x8A, 0xBF, 0xD2, 0x62, 0x7E, 0x15, 0x69, 0x0A, 0x72, 0x7E, 0x69, 0xF5, 0x81, 0xDD, 0x2A, 0x71, 0x27, 0x98, 0x2A, 0x90, 0xE3, 0x3E, 0x2D, 0x4A, 0x03, 0xFE, 0x33, 0x91, 0x42, 0xC7, 0xE4, 0x4C, 0x32, 0x6A, 0xC4, 0x6E, 0xD3, 0x95, 0xA2, 0x25, 0xD3, 0x03, 0x33, 0x89, 0x91, 0x73, 0x28, 0xB4, 0x53, 0x16, 0xB1, 0x58, 0x5A, 0x01, 0xB2, 0xC3, 0x04, 0xB2, 0x94, 0x4E, 0x90, 0x3A, 0xBB, 0xB3, 0xEC, 0x56, 0x19, 0x44, 0x1C, 0xFC, 0x89, 0x65, 0xA4, 0x46, 0xDF, 0x75, 0xDE, 0xFA, 0x80, 0xC6, 0xE1, 0x5A, 0xDB, 0xD5, 0x06, 0xB7, 0xAB, 0x2D, 0xE1, 0x2D, 0xDA, 0x9B, 0xC8, 0x14, 0x41, 0xCF, 0xC8, 0x90, 0x52, 0xE2, 0xE5, 0x80, 0x8F, 0x71, 0x26, 0xC6, 0xFD, 0x3A, 0xC6, 0xAC, 0x80, 0x81, 0x25, 0x8A, 0x84, 0xA0, 0x9A, 0xE5, 0x0F, 0x6C, 0xD7, 0xCC, 0x0F, 0x4A, 0xF3, 0x36, 0xFD, 0x1D, 0x64, 0x3E, 0x99, 0x07, 0x99, 0x96, 0x26, 0x8C, 0x2D, 0x32, 0xD9, 0x09, 0xF2, 0x2E, 0x35, 0x04, 0xF0, 0x7F, 0xBB, 0x56, 0x31, 0x96, 0xD4, 0x31, 0x2F, 0xDD, 0xB9, 0x33, 0x5D, 0x5C, 0x1D, 0x36, 0xE8, 0xC5, 0xEE, 0xA2, 0x27, 0x8D, 0xBA, 0x23, 0xB9, 0x4D, 0x19, 0x3C, 0x94, 0x7C, 0xC4, 0x1C, 0xA9, 0x93, 0xDC, 0x7D, 0xB1, 0x39, 0x63, 0x40, 0xAD, 0x9C, 0x4F, 0xE6, 0x87, 0xDD, 0x7B, 0x8D, 0x0C, 0x7A, 0x51, 0x20, 0xAE, 0x02, 0x04, 0xF2, 0xC6, 0x65, 0xBD, 0x5F, 0x47, 0x3D, 0x64, 0x4C, 0x7F, 0xF2, 0x6B, 0xFF, 0xBA, 0x7A, 0x36, 0x98, 0x08, 0x30, 0x70, 0x21, 0x28, 0xA7, 0xE6, 0x61, 0xD6, 0x77, 0xA0, 0x92, 0xA3, 0x6E, 0x74, 0x28, 0xA4, 0x13, 0x9F, 0xB2, 0x9B, 0x00, 0x95, 0xCC, 0x11, 0x08, 0x6F, 0x44, 0x7D, 0x2A, 0x9E, 0xF6, 0xC9, 0xB1, 0x61, 0xF1, 0x89, 0xC6, 0x29, 0x9E, 0x08, 0x4C, 0xB7, 0xAA, 0x00, 0xFA, 0xF7, 0x87, 0x79, 0x7B, 0xFB, 0x06, 0x9F, 0xBC, 0x08, 0x7F, 0xDE, 0x26, 0x25, 0x2A, 0x16, 0x64, 0xF1, 0x9C, 0x5A, 0x8A, 0x22, 0xEC, 0x5E, 0xE1, 0xAE, 0xB0, 0x76, 0x35, 0x7B, 0x7D, 0xC3, 0x7E, 0x6B, 0x0F, 0x15, 0x20, 0xF9, 0x58, 0xF7, 0x85, 0x1B, 0xAC, 0xB9, 0x2C, 0x89, 0xFD, 0x11, 0x4A, 0x72, 0xFE, 0xAC, 0x54, 0x65, 0x2D, 0x45, 0xB0, 0x9E, 0x1A, 0xE7, 0x65, 0x1A, 0xBD, 0x16, 0x4B, 0xCD, 0x53, 0x7D, 0x58, 0xFA, 0x39, 0xD3, 0xEC, 0x8A, 0xCD, 0xCD, 0xF9, 0x84, 0x25, 0x00, 0x58, 0x62, 0xFA, 0x59, 0x69, 0x2D, 0xE1, 0x62, 0xB7, 0x7E, 0x62, 0x97, 0xC6, 0x62, 0x33, 0x34, 0x84, 0x08, 0xA8, 0xAB, 0x69, 0x5C, 0xE2, 0xF2, 0x72, 0x8D, 0xB9, 0xFB, 0xE2, 0x7E, 0x95, 0x89, 0x67, 0xEC, 0x59, 0x74, 0x76, 0x7C, 0x5A, 0x66, 0x02, 0x30, 0x74, 0xB4, 0xA7, 0x1A, 0xFD, 0x26, 0x4A, 0xD2, 0x89, 0x0E, 0x97, 0x0A, 0x1F, 0x31, 0xD6, 0xE3, 0x31, 0x1B, 0x73, 0x6F, 0x9F, 0x94, 0x88, 0x79, 0x3D, 0xDC, 0x88, 0xF2, 0x34, 0x58, 0x06, 0x42, 0x54, 0xC8, 0x2A, 0x1D, 0x9E, 0x59, 0xEA, 0xD2, 0xFC, 0xEC, 0x40, 0xB4, 0x30, 0x68, 0x7C, 0x4B, 0x7E, 0x28, 0x96, 0x09, 0x26, 0xAF, 0xCA, 0xCC, 0x9B, 0xD7, 0x56, 0xA7, 0x10, 0x88, 0xC7, 0x84, 0x50, 0xE2, 0x0A, 0x2E, 0x98, 0x0A, 0xED, 0xE9, 0xEB, 0xED, 0xFE, 0x7F, 0xAB, 0xD6, 0xAB, 0xFE, 0x96, 0xF9, 0x34, 0xC4, 0xB0, 0x2C, 0x01, 0xCA, 0x19, 0x4D, 0x01, 0xB7, 0x3C, 0x25, 0xD5, 0x99, 0x70, 0x39, 0xD3, 0xFC, 0xD0, 0xF0, 0x99, 0x52, 0x1F, 0x70, 0xCA, 0xEE, 0x69, 0x11, 0x0A, 0xC1, 0xFC, 0x5A, 0x99, 0x91, 0x7A, 0xD7, 0x52, 0xFC, 0x96, 0xAD, 0xFA, 0xD7, 0x18, 0x6D, 0x0A, 0x7C, 0x9C, 0xFE, 0x56, 0x01, 0xC0, 0x75, 0x14, 0xEA, 0x64, 0x48, 0xD6, 0x61, 0xC5, 0x7A, 0xA2, 0x02, 0x42, 0x10, 0x3C, 0x42, 0x76, 0xA0, 0x70, 0xA4, 0x89, 0xA4, 0xCB, 0x6B, 0xCA, 0x0F, 0x9E, 0xCC, 0x43, 0x79, 0xFB, 0x22, 0x02, 0x15, 0xFD, 0x91, 0xF8, 0x10, 0x19, 0xD5, 0xB0, 0xAE, 0x61, 0x93, 0x58, 0xB5, 0x24, 0x68, 0xF2, 0x72, 0xC1, 0x78, 0xE3, 0xA7, 0x4C, 0xF6, 0x77, 0x5A, 0xA9, 0x24, 0xFE, 0x32, 0x9C, 0x31, 0x75, 0xD9, 0xE4, 0xC3, 0xE2, 0x1A, 0xB9, 0xEC, 0x83, 0x6E, 0xDC, 0x3A, 0xCA, 0xB2, 0xE3, 0x89, 0x1E, 0xE8, 0xDE, 0xDA, 0x51, 0x5D, 0x39, 0xAF, 0x9B, 0x8D, 0xDD, 0x0E, 0xE7, 0xB0, 0x16, 0x4F, 0x80, 0x5C, 0x38, 0x35, 0xF6, 0xD2, 0xBA, 0xBD, 0xB3, 0x0E, 0xAB, 0x47, 0x56, 0xE7, 0xEC, 0x7F, 0x82, 0x9E, 0xCE, 0x01, 0xE8, 0xEA, 0xDF, 0xBB, 0xED, 0x12, 0xFC, 0x28, 0x3B, 0x3D, 0x4C, 0x69, 0xF5, 0x75, 0xE7, 0xF8, 0x04, 0x17, 0x68, 0x9F, 0xDF, 0xCF, 0xC7, 0xBE, 0x27, 0xEE, 0x3B, 0x8C, 0xDF, 0x57, 0xAA, 0xEB, 0xEC, 0x4A, 0x95, 0xB7, 0xE5, 0xBB, 0x58, 0x5B, 0x85, 0x22, 0x7F, 0x7C, 0x32, 0xBE, 0x30, 0xDB, 0x3E, 0x65, 0xE4, 0x2E, 0x30, 0xDC, 0xF5, 0xA5, 0xFA, 0x07, 0x3D, 0xBA, 0x39, 0x9D, 0x94, 0x2F, 0x22, 0x22, 0xAD, 0xB9, 0xB9, 0x89, 0x81, 0x02, 0xAF, 0xE5, 0x43, 0x2E, 0xDC, 0x7F, 0x04, 0xAE, 0x34, 0xA8, 0xFE, 0xC2, 0xD8, 0x1C, 0xB4, 0x9A, 0x9A, 0x9B, 0x43, 0x81, 0x4C, 0xE7, 0x1D, 0x97, 0xF7, 0x26, 0xE2, 0xB1, 0xE8, 0xF6, 0x4B, 0x50, 0xE6, 0x5D, 0xFB, 0x48, 0x16, 0xE1, 0x2E, 0x82, 0xA3, 0x19, 0x74, 0x84, 0xA4, 0xE9, 0xBB, 0xA4, 0xD2, 0xD6, 0x9E, 0x3F, 0x19, 0xD0, 0xB7, 0x5C, 0x21, 0xE2, 0xBF, 0xFE, 0x9F, 0xC0, 0xC9, 0x8C, 0xF4, 0x8A, 0x3A, 0xAF, 0x08, 0xD4, 0x67, 0xF7, 0x26, 0x87, 0xDF, 0x01, 0x78, 0x17, 0x4B, 0x78, 0x97, 0xF7, 0x34, 0x34, 0x9B, 0x18, 0x1E, 0xCA, 0x86, 0xA5, 0x98, 0xA0, 0xC5, 0xE8, 0xC2, 0x59, 0x46, 0xF2, 0x4D, 0xC5, 0x57, 0x2B, 0xD3, 0x24, 0xA4, 0x04, 0x58, 0xA7, 0x88, 0xE5, 0x13, 0x7F, 0x3C, 0x7A, 0x7C, 0x97, 0xFC, 0x9F, 0x12, 0xA3, 0xC4, 0x63, 0xA8, 0xFE, 0x94, 0x49, 0x10, 0x1C, 0xCE, 0x96, 0x6D, 0x7C, 0x00, 0x93, 0x23, 0x93, 0x29, 0x98, 0xD5, 0x6E, 0xF4, 0x30, 0xC7, 0x3B, 0xC2, 0x4F, 0x5D, 0x95, 0xF7, 0x37, 0x85, 0x8D, 0xDC, 0x4F, 0x32, 0xC0, 0x13}; -std::vector<uint8_t> ss_KYBER1024 = {0xB1, 0x0F, 0x73, 0x94, 0x92, 0x6A, 0xD3, 0xB4, 0x9C, 0x5D, 0x62, 0xD5, 0xAE, 0xB5, 0x31, 0xD5, 0x75, 0x75, 0x38, 0xBC, 0xC0, 0xDA, 0x9E, 0x55, 0x0D, 0x43, 0x8F, 0x1B, 0x61, 0xBD, 0x74, 0x19}; -std::vector<std::vector<uint8_t>> KYBER1024_pattern = {sk_KYBER1024, ct_KYBER1024, ss_KYBER1024}; +std::vector<uint8_t> sk_MLKEM512 = {0x69, 0xF9, 0xCB, 0xFD, 0x12, 0x37, 0xBA, 0x16, 0x1C, 0xF6, 0xE6, 0xC1, 0x8F, 0x48, 0x8F, 0xC6, 0xE3, 0x9A, 0xB4, 0xA5, 0xC9, 0xE6, 0xC2, 0x2E, 0xA4, 0xE3, 0xAD, 0x8F, 0x26, 0x7A, 0x9C, 0x44, 0x20, 0x10, 0xD3, 0x2E, 0x61, 0xF8, 0x3E, 0x6B, 0xFA, 0x5C, 0x58, 0x70, 0x61, 0x45, 0x37, 0x6D, 0xBB, 0x84, 0x95, 0x28, 0xF6, 0x80, 0x07, 0xC8, 0x22, 0xB3, 0x3A, 0x95, 0xB8, 0x49, 0x04, 0xDC, 0xD2, 0x70, 0x8D, 0x03, 0x40, 0xC8, 0xB8, 0x08, 0xBC, 0xD3, 0xAA, 0xD0, 0xE4, 0x8B, 0x85, 0x84, 0x95, 0x83, 0xA1, 0xB4, 0xE5, 0x94, 0x5D, 0xD9, 0x51, 0x4A, 0x7F, 0x64, 0x61, 0xE0, 0x57, 0xB7, 0xEC, 0xF6, 0x19, 0x57, 0xE9, 0x7C, 0xF6, 0x28, 0x15, 0xF9, 0xC3, 0x22, 0x94, 0xB3, 0x26, 0xE1, 0xA1, 0xC4, 0xE3, 0x60, 0xB9, 0x49, 0x8B, 0xA8, 0x0F, 0x8C, 0xA9, 0x15, 0x32, 0xB1, 0x71, 0xD0, 0xAE, 0xFC, 0x48, 0x49, 0xFA, 0x53, 0xBC, 0x61, 0x79, 0x32, 0xE2, 0x08, 0xA6, 0x77, 0xC6, 0x04, 0x4A, 0x66, 0x00, 0xB8, 0xD8, 0xB8, 0x3F, 0x26, 0xA7, 0x47, 0xB1, 0x8C, 0xFB, 0x78, 0xBE, 0xAF, 0xC5, 0x51, 0xAD, 0x52, 0xB7, 0xCA, 0x6C, 0xB8, 0x8F, 0x3B, 0x5D, 0x9C, 0xE2, 0xAF, 0x6C, 0x67, 0x95, 0x6C, 0x47, 0x8C, 0xEF, 0x49, 0x1F, 0x59, 0xE0, 0x19, 0x1B, 0x3B, 0xBE, 0x92, 0x9B, 0x94, 0xB6, 0x66, 0xC1, 0x76, 0x13, 0x8B, 0x00, 0xF4, 0x97, 0x24, 0x34, 0x1E, 0xE2, 0xE1, 0x64, 0xB9, 0x4C, 0x05, 0x3C, 0x18, 0x5A, 0x51, 0xF9, 0x3E, 0x00, 0xF3, 0x68, 0x61, 0x61, 0x3A, 0x7F, 0xD7, 0x2F, 0xEB, 0xD2, 0x3A, 0x8B, 0x96, 0xA2, 0x60, 0x23, 0x42, 0x39, 0xC9, 0x62, 0x8F, 0x99, 0x5D, 0xC1, 0x38, 0x07, 0xB4, 0x3A, 0x69, 0x46, 0x81, 0x67, 0xCB, 0x1A, 0x8F, 0x9D, 0xD0, 0x7E, 0xE3, 0xB3, 0x32, 0x38, 0xF6, 0x30, 0x96, 0xEB, 0xC4, 0x9D, 0x50, 0x51, 0xC4, 0xB6, 0x59, 0x63, 0xD7, 0x4A, 0x47, 0x66, 0xC2, 0x26, 0xF0, 0xB9, 0x4F, 0x18, 0x62, 0xC2, 0x12, 0x4C, 0x8C, 0x74, 0x97, 0x48, 0xC0, 0xBC, 0x4D, 0xC1, 0x4C, 0xB3, 0x49, 0x06, 0xB8, 0x1C, 0x55, 0x24, 0xFB, 0x81, 0x00, 0x79, 0x85, 0x42, 0xDC, 0x6C, 0xC2, 0xAA, 0x0A, 0x70, 0x85, 0x75, 0xEA, 0xBC, 0xC1, 0x1F, 0x96, 0xA9, 0xE6, 0x1C, 0x01, 0x7A, 0x96, 0xA7, 0xCE, 0x93, 0xC4, 0x20, 0x91, 0x73, 0x71, 0x13, 0xAE, 0x78, 0x3C, 0x0A, 0xE8, 0x75, 0x5E, 0x59, 0x41, 0x11, 0xED, 0xFA, 0xBF, 0xD8, 0x6C, 0x32, 0x12, 0xC6, 0x12, 0xA7, 0xB6, 0x2A, 0xFD, 0x3C, 0x7A, 0x5C, 0x78, 0xB2, 0xF0, 0x73, 0x44, 0xB7, 0x89, 0xC2, 0xB2, 0xDB, 0xB5, 0xF4, 0x44, 0x8B, 0xE9, 0x7B, 0xBA, 0x42, 0x33, 0xC0, 0x03, 0x9C, 0x0F, 0xE8, 0x43, 0x00, 0xF9, 0xB0, 0x3A, 0xC9, 0x94, 0x97, 0xE6, 0xD4, 0x6B, 0x6E, 0x95, 0x30, 0x8F, 0xF8, 0x47, 0x90, 0xF6, 0x12, 0xCF, 0x18, 0x6E, 0xC1, 0x68, 0x11, 0xE8, 0x0C, 0x17, 0x93, 0x16, 0xA6, 0x3B, 0x25, 0x70, 0x3F, 0x60, 0xB8, 0x42, 0xB6, 0x19, 0x07, 0xE6, 0x28, 0x94, 0xE7, 0x36, 0x64, 0x7B, 0x3C, 0x09, 0xDA, 0x6F, 0xEC, 0x59, 0x32, 0x78, 0x2B, 0x36, 0xE0, 0x63, 0x50, 0x85, 0xA3, 0x94, 0x9E, 0x69, 0x4D, 0x7E, 0x17, 0xCB, 0xA3, 0xD9, 0x06, 0x43, 0x30, 0x43, 0x8C, 0x07, 0x1B, 0x58, 0x36, 0xA7, 0x70, 0xC5, 0x5F, 0x62, 0x13, 0xCC, 0x14, 0x25, 0x84, 0x5D, 0xE5, 0xA3, 0x34, 0xD7, 0x5D, 0x3E, 0x50, 0x58, 0xC7, 0x80, 0x9F, 0xDA, 0x4B, 0xCD, 0x78, 0x19, 0x1D, 0xA9, 0x79, 0x73, 0x25, 0xE6, 0x23, 0x6C, 0x26, 0x50, 0xFC, 0x60, 0x4E, 0xE4, 0x3A, 0x83, 0xCE, 0xB3, 0x49, 0x80, 0x08, 0x44, 0x03, 0xA3, 0x32, 0x59, 0x85, 0x79, 0x07, 0x79, 0x9A, 0x9D, 0x2A, 0x71, 0x3A, 0x63, 0x3B, 0x5C, 0x90, 0x47, 0x27, 0xF6, 0x1E, 0x42, 0x52, 0x09, 0x91, 0xD6, 0x55, 0x70, 0x5C, 0xB6, 0xBC, 0x1B, 0x74, 0xAF, 0x60, 0x71, 0x3E, 0xF8, 0x71, 0x2F, 0x14, 0x08, 0x68, 0x69, 0xBE, 0x8E, 0xB2, 0x97, 0xD2, 0x28, 0xB3, 0x25, 0xA0, 0x60, 0x9F, 0xD6, 0x15, 0xEA, 0xB7, 0x08, 0x15, 0x40, 0xA6, 0x1A, 0x82, 0xAB, 0xF4, 0x3B, 0x7D, 0xF9, 0x8A, 0x59, 0x5B, 0xE1, 0x1F, 0x41, 0x6B, 0x41, 0xE1, 0xEB, 0x75, 0xBB, 0x57, 0x97, 0x7C, 0x25, 0xC6, 0x4E, 0x97, 0x43, 0x7D, 0x88, 0xCA, 0x5F, 0xDA, 0x61, 0x59, 0xD6, 0x68, 0xF6, 0xBA, 0xB8, 0x15, 0x75, 0x55, 0xB5, 0xD5, 0x4C, 0x0F, 0x47, 0xCB, 0xCD, 0x16, 0x84, 0x3B, 0x1A, 0x0A, 0x0F, 0x02, 0x10, 0xEE, 0x31, 0x03, 0x13, 0x96, 0x7F, 0x3D, 0x51, 0x64, 0x99, 0x01, 0x8F, 0xDF, 0x31, 0x14, 0x77, 0x24, 0x70, 0xA1, 0x88, 0x9C, 0xC0, 0x6C, 0xB6, 0xB6, 0x69, 0x0A, 0xC3, 0x1A, 0xBC, 0xFA, 0xF4, 0xBC, 0x70, 0x76, 0x84, 0x54, 0x5B, 0x00, 0x0B, 0x58, 0x0C, 0xCB, 0xFC, 0xBC, 0xE9, 0xFA, 0x70, 0xAA, 0xEA, 0x0B, 0xBD, 0x91, 0x10, 0x99, 0x2A, 0x7C, 0x6C, 0x06, 0xCB, 0x36, 0x85, 0x27, 0xFD, 0x22, 0x90, 0x90, 0x75, 0x7E, 0x6F, 0xE7, 0x57, 0x05, 0xFA, 0x59, 0x2A, 0x76, 0x08, 0xF0, 0x50, 0xC6, 0xF8, 0x87, 0x03, 0xCC, 0x28, 0xCB, 0x00, 0x0C, 0x1D, 0x7E, 0x77, 0xB8, 0x97, 0xB7, 0x2C, 0x62, 0xBC, 0xC7, 0xAE, 0xA2, 0x1A, 0x57, 0x72, 0x94, 0x83, 0xD2, 0x21, 0x18, 0x32, 0xBE, 0xD6, 0x12, 0x43, 0x0C, 0x98, 0x31, 0x03, 0xC6, 0x9E, 0x8C, 0x07, 0x2C, 0x0E, 0xA7, 0x89, 0x8F, 0x22, 0x83, 0xBE, 0xC4, 0x8C, 0x5A, 0xC8, 0x19, 0x84, 0xD4, 0xA5, 0xA8, 0x36, 0x19, 0x73, 0x5A, 0x84, 0x2B, 0xD1, 0x72, 0xC0, 0xD1, 0xB3, 0x9F, 0x43, 0x58, 0x8A, 0xF1, 0x70, 0x45, 0x8B, 0xA9, 0xEE, 0x74, 0x92, 0xEA, 0xAA, 0x94, 0xEA, 0x53, 0xA4, 0xD3, 0x84, 0x98, 0xEC, 0xBB, 0x98, 0xA5, 0xF4, 0x07, 0xE7, 0xC9, 0x7B, 0x4E, 0x16, 0x6E, 0x39, 0x71, 0x92, 0xC2, 0x16, 0x03, 0x30, 0x14, 0xB8, 0x78, 0xE9, 0x38, 0x07, 0x5C, 0x6C, 0x1F, 0x10, 0xA0, 0x06, 0x5A, 0xBC, 0x31, 0x63, 0x72, 0x2F, 0x1A, 0x2E, 0xFF, 0xEC, 0x8D, 0x6E, 0x3A, 0x0C, 0x4F, 0x71, 0x74, 0xFC, 0x16, 0xB7, 0x9F, 0xB5, 0x18, 0x6A, 0x75, 0x16, 0x8F, 0x81, 0xA5, 0x6A, 0xA4, 0x8A, 0x20, 0xA0, 0x4B, 0xDD, 0xF1, 0x82, 0xC6, 0xE1, 0x79, 0xC3, 0xF6, 0x90, 0x61, 0x55, 0x5E, 0xF7, 0x39, 0x6D, 0xD0, 0xB7, 0x49, 0x96, 0x01, 0xA6, 0xEB, 0x3A, 0x96, 0xA9, 0xA2, 0x2D, 0x04, 0xF1, 0x16, 0x8D, 0xB5, 0x63, 0x55, 0xB0, 0x76, 0x00, 0xA2, 0x03, 0x70, 0x63, 0x7B, 0x64, 0x59, 0x76, 0xBB, 0xD9, 0x7B, 0x6D, 0x62, 0x88, 0xA0, 0xD3, 0x03, 0x63, 0x60, 0x47, 0x2E, 0x3A, 0xC7, 0x1D, 0x56, 0x6D, 0xB8, 0xFB, 0xB1, 0xB1, 0xD7, 0x6C, 0xB7, 0x55, 0xCD, 0x0D, 0x68, 0xBD, 0xBF, 0xC0, 0x48, 0xEB, 0xA2, 0x52, 0x5E, 0xEA, 0x9D, 0xD5, 0xB1, 0x44, 0xFB, 0x3B, 0x60, 0xFB, 0xC3, 0x42, 0x39, 0x32, 0x0C, 0xBC, 0x06, 0x9B, 0x35, 0xAB, 0x16, 0xB8, 0x75, 0x65, 0x36, 0xFB, 0x33, 0xE8, 0xA6, 0xAF, 0x1D, 0xD4, 0x2C, 0x79, 0xF4, 0x8A, 0xD1, 0x20, 0xAE, 0x4B, 0x15, 0x9D, 0x3D, 0x8C, 0x31, 0x90, 0x60, 0xCC, 0xE5, 0x69, 0xC3, 0xF6, 0x03, 0x53, 0x65, 0x58, 0x5D, 0x34, 0x41, 0x37, 0x95, 0xA6, 0xA1, 0x8E, 0xC5, 0x13, 0x6A, 0xB1, 0x3C, 0x90, 0xE3, 0xAF, 0x14, 0xC0, 0xB8, 0xA4, 0x64, 0xC8, 0x6B, 0x90, 0x73, 0x22, 0x2B, 0x56, 0xB3, 0xF7, 0x32, 0x8A, 0xEA, 0x79, 0x81, 0x55, 0x32, 0x59, 0x11, 0x25, 0x0E, 0xF0, 0x16, 0xD7, 0x28, 0x02, 0xE3, 0x87, 0x8A, 0xA5, 0x05, 0x40, 0xCC, 0x98, 0x39, 0x56, 0x97, 0x1D, 0x6E, 0xFA, 0x35, 0x2C, 0x02, 0x55, 0x4D, 0xC7, 0x60, 0xA5, 0xA9, 0x13, 0x58, 0xEA, 0x56, 0x37, 0x08, 0x84, 0xFD, 0x5B, 0x3F, 0x85, 0xB7, 0x0E, 0x83, 0xE4, 0x69, 0x7D, 0xEB, 0x17, 0x05, 0x16, 0x9E, 0x9C, 0x60, 0xA7, 0x45, 0x28, 0xCF, 0x15, 0x28, 0x1C, 0xB1, 0xB1, 0xC4, 0x57, 0xD4, 0x67, 0xB5, 0xF9, 0x3A, 0x60, 0x37, 0x3D, 0x10, 0xE0, 0xCF, 0x6A, 0x83, 0x7A, 0xA3, 0xC9, 0x59, 0x6A, 0x72, 0xBE, 0xC2, 0x9B, 0x2D, 0x7E, 0x58, 0x65, 0x3D, 0x53, 0x30, 0x61, 0xD3, 0x81, 0xD5, 0x17, 0x59, 0x75, 0x22, 0x17, 0xEB, 0x46, 0xCA, 0xC7, 0x80, 0x7C, 0x4A, 0xD3, 0x8B, 0x61, 0x16, 0x44, 0xAC, 0xF0, 0xA3, 0xF2, 0x6B, 0x6B, 0x08, 0x4A, 0xB4, 0x7A, 0x83, 0xBF, 0x0D, 0x69, 0x6F, 0x8A, 0x47, 0x68, 0xFC, 0x35, 0xBC, 0xA6, 0xBC, 0x79, 0x03, 0xB2, 0xA2, 0x37, 0xC2, 0x77, 0x49, 0xF5, 0x51, 0x0C, 0x86, 0x38, 0x69, 0xE6, 0xAE, 0x56, 0xBB, 0x2A, 0xFE, 0x47, 0x71, 0xC9, 0x22, 0x18, 0x74, 0xF5, 0x0F, 0x5B, 0x14, 0xBA, 0xAD, 0x59, 0x93, 0xB4, 0x92, 0x38, 0xFD, 0x0A, 0x0C, 0x9F, 0x79, 0xB7, 0xB4, 0x58, 0x4E, 0x41, 0x30, 0x1F, 0x7A, 0x88, 0x5C, 0x9F, 0x91, 0x81, 0x9B, 0xEA, 0x00, 0xD5, 0x12, 0x58, 0x17, 0x30, 0x53, 0x9F, 0xB3, 0x7E, 0x59, 0xE8, 0x6A, 0x6D, 0x19, 0xCA, 0x25, 0xF0, 0xA8, 0x11, 0xC9, 0xB4, 0x28, 0xBA, 0x86, 0x14, 0xAA, 0x4F, 0x94, 0x80, 0x7B, 0xC0, 0x31, 0xCB, 0xCC, 0x18, 0x3F, 0x3B, 0xF0, 0x7F, 0xE2, 0xC1, 0xA6, 0xEB, 0xA8, 0x0D, 0x5A, 0x70, 0x6E, 0xE0, 0xDA, 0xB2, 0x7E, 0x23, 0x14, 0x58, 0x02, 0x5D, 0x84, 0xA7, 0xA9, 0xB0, 0x23, 0x05, 0x01, 0x11, 0x6C, 0x29, 0x0A, 0x6B, 0xB5, 0x06, 0x26, 0xD9, 0x7B, 0x93, 0x98, 0x50, 0x94, 0x28, 0x28, 0x39, 0x0B, 0x0A, 0x20, 0x01, 0xB7, 0x85, 0x3A, 0xD1, 0xAE, 0x9B, 0x01, 0x1B, 0x2D, 0xB3, 0x6C, 0xAE, 0xEA, 0x73, 0xA2, 0x32, 0x8E, 0x3C, 0x56, 0x48, 0x5B, 0x49, 0x1C, 0x29, 0x91, 0x15, 0xA0, 0x17, 0xC9, 0x07, 0xAB, 0x54, 0x31, 0x72, 0x60, 0xA5, 0x93, 0xA0, 0xD7, 0xBA, 0x6D, 0x06, 0x61, 0x5D, 0x6E, 0x2C, 0xA8, 0x4B, 0x86, 0x0E, 0xFF, 0x3C, 0xCB, 0x59, 0x72, 0x11, 0xBF, 0xE3, 0x6B, 0xDE, 0xF8, 0x06, 0x9A, 0xFA, 0x36, 0xC5, 0xA7, 0x33, 0x92, 0x72, 0x26, 0x50, 0xE4, 0x95, 0x7D, 0xCA, 0x59, 0x7A, 0xCB, 0xA5, 0x60, 0x5B, 0x63, 0xC1, 0x63, 0xCF, 0xA9, 0x4B, 0x64, 0xDD, 0xD6, 0x23, 0x01, 0xA4, 0x33, 0x20, 0x83, 0x36, 0x19, 0x72, 0x58, 0x9D, 0xB0, 0x59, 0x9A, 0x69, 0x4D, 0xD4, 0x54, 0x7A, 0x5E, 0xE9, 0x19, 0x65, 0x77, 0xC2, 0x2E, 0xD4, 0x27, 0xAC, 0x89, 0xBB, 0x8B, 0xA3, 0x75, 0x3E, 0xB7, 0x6C, 0x41, 0xF2, 0xC1, 0x12, 0x9C, 0x8A, 0x77, 0xD6, 0x80, 0x5F, 0xA7, 0x19, 0xB1, 0xB6, 0xCA, 0x11, 0xB7, 0x40, 0xA7, 0x8A, 0x3D, 0x41, 0xB5, 0x33, 0x05, 0x26, 0xAB, 0x87, 0xD5, 0x8D, 0x59, 0x25, 0x31, 0x5A, 0x14, 0x85, 0xED, 0xC6, 0x47, 0xC1, 0x60, 0x4E, 0xB3, 0x81, 0x38, 0xDE, 0x63, 0x7A, 0xD2, 0xC6, 0xCA, 0x5B, 0xE4, 0x4E, 0x10, 0x08, 0xB2, 0xC0, 0x86, 0x7B, 0x22, 0x9C, 0xCC, 0x36, 0x61, 0x9E, 0x27, 0x58, 0xC4, 0xC2, 0x02, 0x9E, 0xAE, 0xB2, 0x6E, 0x7A, 0x80, 0x3F, 0xCA, 0x30, 0x5A, 0x59, 0xCD, 0x58, 0x5E, 0x11, 0x7D, 0x69, 0x8E, 0xCE, 0x01, 0x1C, 0xC3, 0xFC, 0xE5, 0x4D, 0x2E, 0x11, 0x45, 0x45, 0xA2, 0x1A, 0xC5, 0xBE, 0x67, 0x71, 0xAB, 0x8F, 0x13, 0x12, 0x2F, 0xAD, 0x29, 0x5E, 0x74, 0x5A, 0x50, 0x3B, 0x14, 0x2F, 0x91, 0xAE, 0xF7, 0xBD, 0xE9, 0x99, 0x98, 0x84, 0x5F, 0xDA, 0x04, 0x35, 0x55, 0xC9, 0xC1, 0xEE, 0x53, 0x5B, 0xE1, 0x25, 0xE5, 0xDC, 0xE5, 0xD2, 0x66, 0x66, 0x7E, 0x72, 0x3E, 0x67, 0xB6, 0xBA, 0x89, 0x1C, 0x16, 0xCB, 0xA1, 0x74, 0x09, 0x8A, 0x3F, 0x35, 0x17, 0x78, 0xB0, 0x88, 0x8C, 0x95, 0x90, 0xA9, 0x09, 0x0C, 0xD4, 0x04}; +std::vector<uint8_t> ct_MLKEM512 = {0x16, 0x1C, 0xD2, 0x59, 0xFE, 0xAA, 0x7E, 0xC6, 0xB2, 0x86, 0x49, 0x8A, 0x9A, 0x6F, 0x69, 0xF8, 0xB2, 0x62, 0xA2, 0xE2, 0x09, 0x3D, 0x0F, 0xBD, 0x76, 0xD5, 0xDC, 0x1C, 0x9F, 0xDE, 0x0D, 0xED, 0xB3, 0x65, 0x81, 0x00, 0x4C, 0xB4, 0x81, 0x12, 0xF8, 0x52, 0xE7, 0xF8, 0x7F, 0x64, 0x9E, 0x8A, 0x42, 0xCD, 0x9E, 0x03, 0x49, 0xE7, 0xDA, 0xBD, 0xF0, 0xA9, 0xAC, 0x1B, 0x52, 0x1C, 0x37, 0xEA, 0x52, 0x41, 0x37, 0x0A, 0x8A, 0xB2, 0x91, 0x1C, 0xC7, 0x99, 0x02, 0xC9, 0x5D, 0x28, 0x22, 0x4F, 0xA8, 0x89, 0x6A, 0xD7, 0x15, 0x20, 0x9E, 0xCD, 0xD5, 0xD7, 0x84, 0xE9, 0x1D, 0xD9, 0xD0, 0xBE, 0x91, 0x6B, 0x45, 0x65, 0xF4, 0xD5, 0x66, 0x9A, 0xEE, 0x0D, 0xEF, 0x93, 0x1E, 0x97, 0x68, 0x29, 0x4E, 0xEC, 0x52, 0x58, 0xDE, 0x83, 0x91, 0xEC, 0xE2, 0x71, 0xE7, 0xE4, 0xCF, 0xD9, 0xD2, 0x3A, 0x79, 0xFA, 0xC3, 0xA8, 0xE0, 0xDB, 0x5D, 0xDD, 0x6E, 0x01, 0x07, 0x23, 0x56, 0x88, 0xBB, 0xDF, 0x7B, 0xC5, 0xD5, 0x63, 0x2F, 0x20, 0x6C, 0x63, 0xA0, 0xC9, 0x56, 0x4F, 0x30, 0x96, 0x5C, 0xA5, 0x8C, 0x69, 0xFF, 0x92, 0xD2, 0x5A, 0x4F, 0x93, 0xA0, 0x9E, 0xAB, 0x9B, 0x90, 0x85, 0x94, 0x7E, 0x07, 0x8A, 0x23, 0xE4, 0xD9, 0xC1, 0x3B, 0x8A, 0x56, 0xE7, 0x3E, 0x18, 0xDF, 0x42, 0xD6, 0x94, 0x9F, 0xAF, 0x59, 0x21, 0xF2, 0xE3, 0x73, 0xD4, 0x50, 0xC8, 0xC0, 0x9D, 0x07, 0xB1, 0x52, 0xA9, 0x7C, 0x24, 0x54, 0x47, 0x42, 0x94, 0x81, 0xD4, 0x98, 0xBE, 0xB7, 0x25, 0x6B, 0xC4, 0x7F, 0x68, 0xF9, 0x92, 0x2B, 0x0B, 0x1C, 0x62, 0xD9, 0xC2, 0x3F, 0x9F, 0x73, 0x3D, 0xD7, 0x37, 0x92, 0xCF, 0xC7, 0xB4, 0x3C, 0xBC, 0xEA, 0x27, 0x7D, 0x51, 0xB2, 0xB8, 0xAD, 0x4A, 0x4F, 0x52, 0x2F, 0x64, 0x2C, 0xAD, 0x5C, 0x5D, 0xEB, 0x21, 0xF3, 0x62, 0x7F, 0x8A, 0xF4, 0xD3, 0xE5, 0xBC, 0x9E, 0x91, 0xD4, 0xCB, 0x2F, 0x12, 0x4B, 0x5B, 0xD7, 0xC2, 0xF4, 0xA0, 0x50, 0xCA, 0x75, 0x5B, 0xDB, 0x80, 0x56, 0x60, 0x96, 0x63, 0xFB, 0x95, 0x11, 0xC9, 0xAD, 0x83, 0xB5, 0x03, 0x90, 0x88, 0xCC, 0x01, 0xF0, 0xDD, 0x54, 0x35, 0x3B, 0x0D, 0xD7, 0x43, 0x3F, 0x0C, 0x6C, 0xEE, 0x0D, 0x07, 0x59, 0x59, 0x81, 0x0D, 0xEC, 0x54, 0x16, 0x52, 0x2B, 0xB1, 0xF1, 0xF6, 0x55, 0x47, 0xA0, 0xC2, 0xE9, 0xCC, 0x9B, 0xC1, 0x7F, 0x8D, 0x39, 0xD2, 0x93, 0x09, 0xEB, 0xE7, 0x9F, 0x21, 0x33, 0x1B, 0x75, 0xE1, 0x2A, 0xF2, 0xE9, 0x3F, 0x03, 0xF7, 0x4F, 0x7F, 0x87, 0xD3, 0x60, 0xF1, 0xDA, 0xF8, 0x6C, 0xED, 0x73, 0x60, 0x92, 0xA2, 0x11, 0xA8, 0x15, 0x88, 0x59, 0xC4, 0x2E, 0x22, 0x3C, 0xFE, 0x2E, 0x6E, 0x55, 0x34, 0x37, 0xD8, 0x05, 0x76, 0xCF, 0xD1, 0x94, 0x4E, 0x97, 0xEE, 0xFF, 0x9B, 0x49, 0xE5, 0xEC, 0xCF, 0xC6, 0x78, 0xEE, 0x16, 0x52, 0x68, 0xDF, 0xE3, 0xD3, 0x59, 0x6B, 0x4B, 0x86, 0x20, 0x4A, 0x81, 0xC6, 0x06, 0x3B, 0x0C, 0xDC, 0xE6, 0x19, 0xFD, 0xBB, 0x96, 0xDF, 0x7D, 0xE6, 0xE0, 0xBD, 0x52, 0x70, 0xB4, 0xD5, 0x9C, 0x4D, 0xC5, 0x08, 0x47, 0x6E, 0x7F, 0x07, 0x08, 0xF9, 0x8C, 0x7A, 0x4F, 0x66, 0x45, 0xC4, 0x9D, 0x06, 0x10, 0x0C, 0x76, 0x0C, 0x59, 0x95, 0x28, 0xD1, 0xB8, 0xBB, 0xFE, 0x62, 0x81, 0x91, 0xCC, 0x08, 0x3C, 0x8D, 0x22, 0x5A, 0x09, 0x3F, 0x9F, 0x17, 0xE3, 0x55, 0x74, 0x98, 0x6F, 0x86, 0xBA, 0xA4, 0x68, 0x98, 0xB5, 0x89, 0xF3, 0xCB, 0x7D, 0xB4, 0x6A, 0x45, 0xF3, 0xED, 0xD4, 0xFA, 0xC2, 0x08, 0x08, 0xF4, 0xCD, 0x02, 0x49, 0xDA, 0x69, 0x3F, 0x8F, 0xAB, 0xFB, 0xD4, 0xE1, 0x0C, 0x02, 0xC6, 0x5B, 0xA8, 0xC8, 0x61, 0x0F, 0xA8, 0xC6, 0xDF, 0x3D, 0xBA, 0xEB, 0x67, 0x63, 0xDD, 0x48, 0x2A, 0xF4, 0x15, 0x58, 0xB1, 0xE1, 0x5C, 0xC9, 0xC7, 0xA7, 0x2E, 0x07, 0x16, 0x85, 0xAC, 0x19, 0xA0, 0x51, 0xF1, 0x92, 0x45, 0xB9, 0xF7, 0x7C, 0x30, 0x38, 0xA5, 0x4E, 0x29, 0x58, 0x62, 0x3E, 0xB8, 0x10, 0x59, 0x55, 0x60, 0x9E, 0x27, 0xD6, 0x7C, 0xF7, 0x2E, 0xC5, 0xC4, 0xA8, 0xE9, 0xB9, 0xC2, 0x92, 0x4A, 0x9E, 0x22, 0x98, 0x50, 0x8B, 0xAB, 0xA1, 0x3C, 0xF1, 0x11, 0xFD, 0xFB, 0x06, 0x2C, 0x96, 0x07, 0xAC, 0x1A, 0xAA, 0x6C, 0x63, 0x73, 0x10, 0xA8, 0x89, 0x4B, 0xF0, 0xB9, 0x6F, 0x0C, 0x19, 0x13, 0x61, 0x86, 0xB6, 0x18, 0xDF, 0xFB, 0x27, 0x55, 0x28, 0xBE, 0xD1, 0xCC, 0x27, 0x15, 0xDE, 0xF4, 0x12, 0xF7, 0x7A, 0x3C, 0xF9, 0x66, 0x45, 0x73, 0x3B, 0x04, 0x8A, 0x78, 0x47, 0x43, 0x20, 0xD1, 0xA3, 0x80, 0xF5, 0xEE, 0xDB, 0xDA, 0x21, 0xFA, 0x01, 0x25, 0xC9, 0x1D, 0x3C, 0x37, 0xC5, 0x4B, 0xF3, 0x75, 0x2A, 0x1F, 0x84, 0x71, 0xC8, 0x1F, 0xCA, 0xE2, 0xD3, 0xED, 0xA9, 0x66, 0xE1, 0x4E, 0x66, 0xF2, 0x23, 0xB0, 0x54, 0xD7, 0x98, 0x48, 0xFF, 0x94, 0x11, 0xD6, 0x34, 0x02, 0x4A, 0x09, 0x89, 0x70, 0xAD, 0xE6, 0xA8, 0x8B, 0x5F, 0x90, 0x69, 0xF7, 0x60, 0x58, 0x4D, 0xC4, 0xCF, 0xFF, 0xCE, 0xA8, 0xEC, 0xE1, 0x1B, 0xB5, 0x56, 0x6B, 0xD2, 0x36, 0x0A, 0xB7, 0x07, 0xDF, 0x2D, 0x21, 0xB6, 0x74, 0x88, 0xD9, 0x31, 0xF0, 0x20, 0x06, 0x91, 0x76, 0x42, 0x3E, 0x69, 0x44, 0x49, 0x0C, 0xB3, 0x85, 0xE7, 0x0B, 0x35, 0x8A, 0x25, 0x34, 0x6B, 0xAF, 0xCD, 0xD0, 0x6D, 0x40, 0x2F, 0xF2, 0x4D, 0x6C, 0x1E, 0x5F, 0x61, 0xA8, 0x5D}; +std::vector<uint8_t> ss_MLKEM512 = {0xDF, 0x46, 0x2A, 0xD6, 0x8F, 0x1E, 0xC8, 0x97, 0x2E, 0xD9, 0xB0, 0x2D, 0x6D, 0xE0, 0x60, 0x4B, 0xDE, 0xC7, 0x57, 0x20, 0xE0, 0x50, 0x49, 0x73, 0x51, 0xE6, 0xEC, 0x93, 0x3E, 0x71, 0xF8, 0x82}; + +std::vector<uint8_t> sk_MLKEM1024 = {0x84, 0x45, 0xC3, 0x36, 0xF3, 0x51, 0x8B, 0x29, 0x81, 0x63, 0xDC, 0xBB, 0x63, 0x57, 0x59, 0x79, 0x83, 0xCA, 0x2E, 0x87, 0x3D, 0xCB, 0x49, 0x61, 0x0C, 0xF5, 0x2F, 0x14, 0xDB, 0xCB, 0x94, 0x7C, 0x1F, 0x3E, 0xE9, 0x26, 0x69, 0x67, 0x27, 0x6B, 0x0C, 0x57, 0x6C, 0xF7, 0xC3, 0x0E, 0xE6, 0xB9, 0x3D, 0xEA, 0x51, 0x18, 0x67, 0x6C, 0xBE, 0xE1, 0xB1, 0xD4, 0x79, 0x42, 0x06, 0xFB, 0x36, 0x9A, 0xBA, 0x41, 0x16, 0x7B, 0x43, 0x93, 0x85, 0x5C, 0x84, 0xEB, 0xA8, 0xF3, 0x23, 0x73, 0xC0, 0x5B, 0xAE, 0x76, 0x31, 0xC8, 0x02, 0x74, 0x4A, 0xAD, 0xB6, 0xC2, 0xDE, 0x41, 0x25, 0x0C, 0x49, 0x43, 0x15, 0x23, 0x0B, 0x52, 0x82, 0x6C, 0x34, 0x58, 0x7C, 0xB2, 0x1B, 0x18, 0x3B, 0x49, 0xB2, 0xA5, 0xAC, 0x04, 0x92, 0x1A, 0xC6, 0xBF, 0xAC, 0x1B, 0x24, 0xA4, 0xB3, 0x7A, 0x93, 0xA4, 0xB1, 0x68, 0xCC, 0xE7, 0x59, 0x1B, 0xE6, 0x11, 0x1F, 0x47, 0x62, 0x60, 0xF2, 0x76, 0x29, 0x59, 0xF5, 0xC1, 0x64, 0x01, 0x18, 0xC2, 0x42, 0x37, 0x72, 0xE2, 0xAD, 0x03, 0xDC, 0x71, 0x68, 0xA3, 0x8C, 0x6D, 0xD3, 0x9F, 0x5F, 0x72, 0x54, 0x26, 0x42, 0x80, 0xC8, 0xBC, 0x10, 0xB9, 0x14, 0x16, 0x80, 0x70, 0x47, 0x2F, 0xA8, 0x80, 0xAC, 0xB8, 0x60, 0x1A, 0x8A, 0x08, 0x37, 0xF2, 0x5F, 0xE1, 0x94, 0x68, 0x7C, 0xD6, 0x8B, 0x7D, 0xE2, 0x34, 0x0F, 0x03, 0x6D, 0xAD, 0x89, 0x1D, 0x38, 0xD1, 0xB0, 0xCE, 0x9C, 0x26, 0x33, 0x35, 0x5C, 0xF5, 0x7B, 0x50, 0xB8, 0x96, 0x03, 0x6F, 0xCA, 0x26, 0x0D, 0x26, 0x69, 0xF8, 0x5B, 0xAC, 0x79, 0x71, 0x4F, 0xDA, 0xFB, 0x41, 0xEF, 0x80, 0xB8, 0xC3, 0x02, 0x64, 0xC3, 0x13, 0x86, 0xAE, 0x60, 0xB0, 0x5F, 0xAA, 0x54, 0x2A, 0x26, 0xB4, 0x1E, 0xB8, 0x5F, 0x67, 0x06, 0x8F, 0x08, 0x80, 0x34, 0xFF, 0x67, 0xAA, 0x2E, 0x81, 0x5A, 0xAB, 0x8B, 0xCA, 0x6B, 0xF7, 0x1F, 0x70, 0xEC, 0xC3, 0xCB, 0xCB, 0xC4, 0x5E, 0xF7, 0x01, 0xFC, 0xD5, 0x42, 0xBD, 0x21, 0xC7, 0xB0, 0x95, 0x68, 0xF3, 0x69, 0xC6, 0x69, 0xF3, 0x96, 0x47, 0x38, 0x44, 0xFB, 0xA1, 0x49, 0x57, 0xF5, 0x19, 0x74, 0xD8, 0x52, 0xB9, 0x78, 0x01, 0x46, 0x03, 0xA2, 0x10, 0xC0, 0x19, 0x03, 0x62, 0x87, 0x00, 0x89, 0x94, 0xF2, 0x12, 0x55, 0xB2, 0x50, 0x99, 0xAD, 0x82, 0xAA, 0x13, 0x24, 0x38, 0x96, 0x3B, 0x2C, 0x0A, 0x47, 0xCD, 0xF5, 0xF3, 0x2B, 0xA4, 0x6B, 0x76, 0xC7, 0xA6, 0x55, 0x9F, 0x18, 0xBF, 0xD5, 0x55, 0xB7, 0x62, 0xE4, 0x87, 0xB6, 0xAC, 0x99, 0x2F, 0xE2, 0x0E, 0x28, 0x3C, 0xA0, 0xB3, 0xF6, 0x16, 0x44, 0x96, 0x95, 0x59, 0x95, 0xC3, 0xB2, 0x8A, 0x57, 0xBB, 0xC2, 0x98, 0x26, 0xF0, 0x6F, 0xB3, 0x8B, 0x25, 0x34, 0x70, 0xAF, 0x63, 0x1B, 0xC4, 0x6C, 0x3A, 0x8F, 0x9C, 0xE8, 0x24, 0x32, 0x19, 0x85, 0xDD, 0x01, 0xC0, 0x5F, 0x69, 0xB8, 0x24, 0xF9, 0x16, 0x63, 0x3B, 0x40, 0x65, 0x4C, 0x75, 0xAA, 0xEB, 0x93, 0x85, 0x57, 0x6F, 0xFD, 0xE2, 0x99, 0x0A, 0x6B, 0x0A, 0x3B, 0xE8, 0x29, 0xD6, 0xD8, 0x4E, 0x34, 0xF1, 0x78, 0x05, 0x89, 0xC7, 0x92, 0x04, 0xC6, 0x3C, 0x79, 0x8F, 0x55, 0xD2, 0x31, 0x87, 0xE4, 0x61, 0xD4, 0x8C, 0x21, 0xE5, 0xC0, 0x47, 0xE5, 0x35, 0xB1, 0x9F, 0x45, 0x8B, 0xBA, 0x13, 0x45, 0xB9, 0xE4, 0x1E, 0x0C, 0xB4, 0xA9, 0xC2, 0xD8, 0xC4, 0x0B, 0x49, 0x0A, 0x3B, 0xAB, 0xC5, 0x53, 0xB3, 0x02, 0x6B, 0x16, 0x72, 0xD2, 0x8C, 0xBC, 0x8B, 0x49, 0x8A, 0x3A, 0x99, 0x57, 0x9A, 0x83, 0x2F, 0xEA, 0xE7, 0x46, 0x10, 0xF0, 0xB6, 0x25, 0x0C, 0xC3, 0x33, 0xE9, 0x49, 0x3E, 0xB1, 0x62, 0x1E, 0xD3, 0x4A, 0xA4, 0xAB, 0x17, 0x5F, 0x2C, 0xA2, 0x31, 0x15, 0x25, 0x09, 0xAC, 0xB6, 0xAC, 0x86, 0xB2, 0x0F, 0x6B, 0x39, 0x10, 0x84, 0x39, 0xE5, 0xEC, 0x12, 0xD4, 0x65, 0xA0, 0xFE, 0xF3, 0x50, 0x03, 0xE1, 0x42, 0x77, 0xA2, 0x18, 0x12, 0x14, 0x6B, 0x25, 0x44, 0x71, 0x6D, 0x6A, 0xB8, 0x2D, 0x1B, 0x07, 0x26, 0xC2, 0x7A, 0x98, 0xD5, 0x89, 0xEB, 0xDA, 0xCC, 0x4C, 0x54, 0xBA, 0x77, 0xB2, 0x49, 0x8F, 0x21, 0x7E, 0x14, 0xE3, 0x4E, 0x66, 0x02, 0x5A, 0x2A, 0x14, 0x3A, 0x99, 0x25, 0x20, 0xA6, 0x1C, 0x06, 0x72, 0xCC, 0x9C, 0xCE, 0xD7, 0xC9, 0x45, 0x0C, 0x68, 0x3E, 0x90, 0xA3, 0xE4, 0x65, 0x1D, 0xB6, 0x23, 0xA6, 0xDB, 0x39, 0xAC, 0x26, 0x12, 0x5B, 0x7F, 0xC1, 0x98, 0x6D, 0x7B, 0x04, 0x93, 0xB8, 0xB7, 0x2D, 0xE7, 0x70, 0x7D, 0xC2, 0x0B, 0xBD, 0xD4, 0x37, 0x13, 0x15, 0x6A, 0xF7, 0xD9, 0x43, 0x0E, 0xF4, 0x53, 0x99, 0x66, 0x3C, 0x22, 0x02, 0x73, 0x91, 0x68, 0x69, 0x2D, 0xD6, 0x57, 0x54, 0x5B, 0x05, 0x6D, 0x9C, 0x92, 0x38, 0x5A, 0x7F, 0x41, 0x4B, 0x34, 0xB9, 0x0C, 0x79, 0x60, 0xD5, 0x7B, 0x35, 0xBA, 0x7D, 0xDE, 0x7B, 0x81, 0xFC, 0xA0, 0x11, 0x9D, 0x74, 0x1B, 0x12, 0x78, 0x09, 0x26, 0x01, 0x8F, 0xE4, 0xC8, 0x03, 0x0B, 0xF0, 0x38, 0xE1, 0x8B, 0x4F, 0xA3, 0x37, 0x43, 0xD0, 0xD3, 0xC8, 0x46, 0x41, 0x7E, 0x9D, 0x59, 0x15, 0xC2, 0x46, 0x31, 0x59, 0x38, 0xB1, 0xE2, 0x33, 0x61, 0x45, 0x01, 0xD0, 0x26, 0x95, 0x95, 0x51, 0x25, 0x8B, 0x23, 0x32, 0x30, 0xD4, 0x28, 0xB1, 0x81, 0xB1, 0x32, 0xF1, 0xD0, 0xB0, 0x26, 0x06, 0x7B, 0xA8, 0x16, 0x99, 0x9B, 0xC0, 0xCD, 0x6B, 0x54, 0x7E, 0x54, 0x8B, 0x63, 0xC9, 0xEA, 0xA0, 0x91, 0xBA, 0xC4, 0x93, 0xDC, 0x59, 0x8D, 0xBC, 0x2B, 0x0E, 0x14, 0x6A, 0x25, 0x91, 0xC2, 0xA8, 0xC0, 0x09, 0xDD, 0x51, 0x70, 0xAA, 0xE0, 0x27, 0xC5, 0x41, 0xA1, 0xB5, 0xE6, 0x6E, 0x45, 0xC6, 0x56, 0x12, 0x98, 0x4C, 0x46, 0x77, 0x04, 0x93, 0xEC, 0x89, 0x6E, 0xF2, 0x5A, 0xA9, 0x30, 0x5E, 0x9F, 0x06, 0x69, 0x2C, 0xD0, 0xB2, 0xF0, 0x69, 0x62, 0xE2, 0x05, 0xBE, 0xBE, 0x11, 0x3A, 0x34, 0xEB, 0xB1, 0xA4, 0x83, 0x0A, 0x9B, 0x37, 0x49, 0x64, 0x1B, 0xB9, 0x35, 0x00, 0x7B, 0x23, 0xB2, 0x4B, 0xFE, 0x57, 0x69, 0x56, 0x25, 0x4D, 0x7A, 0x35, 0xAA, 0x49, 0x6A, 0xC4, 0x46, 0xC6, 0x7A, 0x7F, 0xEC, 0x85, 0xA6, 0x00, 0x57, 0xE8, 0x58, 0x06, 0x17, 0xBC, 0xB3, 0xFA, 0xD1, 0x5C, 0x76, 0x44, 0x0F, 0xED, 0x54, 0xCC, 0x78, 0x93, 0x94, 0xFE, 0xA2, 0x44, 0x52, 0xCC, 0x6B, 0x05, 0x85, 0xB7, 0xEB, 0x0A, 0x88, 0xBB, 0xA9, 0x50, 0x0D, 0x98, 0x00, 0xE6, 0x24, 0x1A, 0xFE, 0xB5, 0x23, 0xB5, 0x5A, 0x96, 0xA5, 0x35, 0x15, 0x1D, 0x10, 0x49, 0x57, 0x32, 0x06, 0xE5, 0x9C, 0x7F, 0xEB, 0x07, 0x09, 0x66, 0x82, 0x36, 0x34, 0xF7, 0x7D, 0x5F, 0x12, 0x91, 0x75, 0x5A, 0x24, 0x31, 0x19, 0x62, 0x1A, 0xF8, 0x08, 0x4A, 0xB7, 0xAC, 0x1E, 0x22, 0xA0, 0x56, 0x8C, 0x62, 0x01, 0x41, 0x7C, 0xBE, 0x36, 0x55, 0xD8, 0xA0, 0x8D, 0xD5, 0xB5, 0x13, 0x88, 0x4C, 0x98, 0xD5, 0xA4, 0x93, 0xFD, 0x49, 0x38, 0x2E, 0xA4, 0x18, 0x60, 0xF1, 0x33, 0xCC, 0xD6, 0x01, 0xE8, 0x85, 0x96, 0x64, 0x26, 0xA2, 0xB1, 0xF2, 0x3D, 0x42, 0xD8, 0x2E, 0x24, 0x58, 0x2D, 0x99, 0x72, 0x51, 0x92, 0xC2, 0x17, 0x77, 0x46, 0x7B, 0x14, 0x57, 0xB1, 0xDD, 0x42, 0x9A, 0x0C, 0x41, 0xA5, 0xC3, 0xD7, 0x04, 0xCE, 0xA0, 0x62, 0x78, 0xC5, 0x99, 0x41, 0xB4, 0x38, 0xC6, 0x27, 0x27, 0x09, 0x78, 0x09, 0xB4, 0x53, 0x0D, 0xBE, 0x83, 0x7E, 0xA3, 0x96, 0xB6, 0xD3, 0x10, 0x77, 0xFA, 0xD3, 0x73, 0x30, 0x53, 0x98, 0x9A, 0x84, 0x42, 0xAA, 0xC4, 0x25, 0x5C, 0xB1, 0x63, 0xB8, 0xCA, 0x2F, 0x27, 0x50, 0x1E, 0xA9, 0x67, 0x30, 0x56, 0x95, 0xAB, 0xD6, 0x59, 0xAA, 0x02, 0xC8, 0x3E, 0xE6, 0x0B, 0xB5, 0x74, 0x20, 0x3E, 0x99, 0x37, 0xAE, 0x1C, 0x62, 0x1C, 0x8E, 0xCB, 0x5C, 0xC1, 0xD2, 0x1D, 0x55, 0x69, 0x60, 0xB5, 0xB9, 0x16, 0x1E, 0xA9, 0x6F, 0xFF, 0xEB, 0xAC, 0x72, 0xE1, 0xB8, 0xA6, 0x15, 0x4F, 0xC4, 0xD8, 0x8B, 0x56, 0xC0, 0x47, 0x41, 0xF0, 0x90, 0xCB, 0xB1, 0x56, 0xA7, 0x37, 0xC9, 0xE6, 0xA2, 0x2B, 0xA8, 0xAC, 0x70, 0x4B, 0xC3, 0x04, 0xF8, 0xE1, 0x7E, 0x5E, 0xA8, 0x45, 0xFD, 0xE5, 0x9F, 0xBF, 0x78, 0x8C, 0xCE, 0x0B, 0x97, 0xC8, 0x76, 0x1F, 0x89, 0xA2, 0x42, 0xF3, 0x05, 0x25, 0x83, 0xC6, 0x84, 0x4A, 0x63, 0x20, 0x31, 0xC9, 0x64, 0xA6, 0xC4, 0xA8, 0x5A, 0x12, 0x8A, 0x28, 0x61, 0x9B, 0xA1, 0xBB, 0x3D, 0x1B, 0xEA, 0x4B, 0x49, 0x84, 0x1F, 0xC8, 0x47, 0x61, 0x4A, 0x06, 0x68, 0x41, 0xF5, 0x2E, 0xD0, 0xEB, 0x8A, 0xE0, 0xB8, 0xB0, 0x96, 0xE9, 0x2B, 0x81, 0x95, 0x40, 0x58, 0x15, 0xB2, 0x31, 0x26, 0x6F, 0x36, 0xB1, 0x8C, 0x1A, 0x53, 0x33, 0x3D, 0xAB, 0x95, 0xD2, 0xA9, 0xA3, 0x74, 0xB5, 0x47, 0x8A, 0x4A, 0x41, 0xFB, 0x87, 0x59, 0x95, 0x7C, 0x9A, 0xB2, 0x2C, 0xAE, 0x54, 0x5A, 0xB5, 0x44, 0xBA, 0x8D, 0xD0, 0x5B, 0x83, 0xF3, 0xA6, 0x13, 0xA2, 0x43, 0x7A, 0xDB, 0x07, 0x3A, 0x96, 0x35, 0xCB, 0x4B, 0xBC, 0x96, 0x5F, 0xB4, 0x54, 0xCF, 0x27, 0xB2, 0x98, 0xA4, 0x0C, 0xD0, 0xDA, 0x3B, 0x8F, 0x9C, 0xA9, 0x9D, 0x8C, 0xB4, 0x28, 0x6C, 0x5E, 0xB4, 0x76, 0x41, 0x67, 0x96, 0x07, 0x0B, 0xA5, 0x35, 0xAA, 0xA5, 0x8C, 0xDB, 0x45, 0x1C, 0xD6, 0xDB, 0x5C, 0xBB, 0x0C, 0xA2, 0x0F, 0x0C, 0x71, 0xDE, 0x97, 0xC3, 0x0D, 0xA9, 0x7E, 0xC7, 0x90, 0x6D, 0x06, 0xB4, 0xB9, 0x39, 0x39, 0x60, 0x28, 0xC4, 0x6B, 0xA0, 0xE7, 0xA8, 0x65, 0xBC, 0x83, 0x08, 0xA3, 0x81, 0x0F, 0x12, 0x12, 0x00, 0x63, 0x39, 0xF7, 0xBC, 0x16, 0x9B, 0x16, 0x66, 0xFD, 0xF4, 0x75, 0x91, 0x1B, 0xBC, 0x8A, 0xAA, 0xB4, 0x17, 0x55, 0xC9, 0xA8, 0xAA, 0xBF, 0xA2, 0x3C, 0x0E, 0x37, 0xF8, 0x4F, 0xE4, 0x69, 0x99, 0xE0, 0x30, 0x49, 0x4B, 0x92, 0x98, 0xEF, 0x99, 0x34, 0xE8, 0xA6, 0x49, 0xC0, 0xA5, 0xCC, 0xE2, 0xB2, 0x2F, 0x31, 0x80, 0x9A, 0xFE, 0xD2, 0x39, 0x55, 0xD8, 0x78, 0x81, 0xD9, 0x9F, 0xC1, 0xD3, 0x52, 0x89, 0x6C, 0xAC, 0x90, 0x55, 0xBE, 0xA0, 0xD0, 0x16, 0xCC, 0xBA, 0x78, 0x05, 0xA3, 0xA5, 0x0E, 0x22, 0x16, 0x30, 0x37, 0x9B, 0xD0, 0x11, 0x35, 0x22, 0x1C, 0xAD, 0x5D, 0x95, 0x17, 0xC8, 0xCC, 0x42, 0x63, 0x7B, 0x9F, 0xC0, 0x71, 0x8E, 0x9A, 0x9B, 0xB4, 0x94, 0x5C, 0x72, 0xD8, 0xD1, 0x1D, 0x3D, 0x65, 0x9D, 0x83, 0xA3, 0xC4, 0x19, 0x50, 0x9A, 0xF5, 0xB4, 0x70, 0xDD, 0x89, 0xB7, 0xF3, 0xAC, 0xCF, 0x5F, 0x35, 0xCF, 0xC3, 0x22, 0x11, 0x5F, 0xD6, 0x6A, 0x5C, 0xD2, 0x87, 0x56, 0x51, 0x32, 0x6F, 0x9B, 0x31, 0x68, 0x91, 0x3B, 0xE5, 0xB9, 0xC8, 0x7A, 0xE0, 0xB0, 0x25, 0xEC, 0x7A, 0x2F, 0x4A, 0x07, 0x27, 0x50, 0x94, 0x6A, 0xC6, 0x11, 0x70, 0xA7, 0x82, 0x6D, 0x97, 0x04, 0xC5, 0xA2, 0x3A, 0x1C, 0x0A, 0x23, 0x25, 0x14, 0x6C, 0x3B, 0xC1, 0x85, 0x88, 0x26, 0xC6, 0xB3, 0x92, 0x79, 0xC2, 0xDA, 0x74, 0x38, 0xA3, 0x70, 0xED, 0x8A, 0x0A, 0xA5, 0x16, 0x9E, 0x3B, 0xEC, 0x29, 0xED, 0x88, 0x47, 0x87, 0x32, 0x75, 0x8D, 0x45, 0x41, 0x43, 0xE2, 0x27, 0xF8, 0x59, 0x58, 0x83, 0x29, 0x78, 0x42, 0xE6, 0xAF, 0x13, 0x3B, 0x17, 0xE4, 0x81, 0x1B, 0x0F, 0x57, 0x13, 0xAC, 0x73, 0xB7, 0xE3, 0x47, 0x42, 0x3E, 0xB9, 0x28, 0x22, 0xD2, 0x30, 0x6F, 0xA1, 0x45, 0x00, 0xA7, 0x20, 0x7A, 0x06, 0x72, 0x67, 0x20, 0x46, 0x54, 0x4A, 0xCC, 0x4E, 0xA9, 0xC1, 0x6E, 0xD7, 0x42, 0x1A, 0x06, 0x9E, 0x0D, 0x73, 0x7A, 0x98, 0x62, 0x85, 0x19, 0xC6, 0xA2, 0x9A, 0x42, 0x4A, 0x86, 0x8B, 0x46, 0xD9, 0xA0, 0xCC, 0x7C, 0x6C, 0x9D, 0xDD, 0x8B, 0x8B, 0xCB, 0xF4, 0x22, 0xC8, 0xF4, 0x8A, 0x73, 0x14, 0x3D, 0x5A, 0xBB, 0x66, 0xBC, 0x55, 0x49, 0x94, 0x18, 0x43, 0x08, 0x02, 0xBA, 0xC5, 0x44, 0x46, 0x3C, 0xC7, 0x31, 0x9D, 0x17, 0x99, 0x8F, 0x29, 0x41, 0x13, 0x65, 0x76, 0x6D, 0x04, 0xC8, 0x47, 0xF3, 0x12, 0x9D, 0x90, 0x77, 0xB7, 0xD8, 0x33, 0x9B, 0xFB, 0x96, 0xA6, 0x73, 0x9C, 0x3F, 0x6B, 0x74, 0xA8, 0xF0, 0x5F, 0x91, 0x38, 0xAB, 0x2F, 0xE3, 0x7A, 0xCB, 0x57, 0x63, 0x4D, 0x18, 0x20, 0xB5, 0x01, 0x76, 0xF5, 0xA0, 0xB6, 0xBC, 0x29, 0x40, 0xF1, 0xD5, 0x93, 0x8F, 0x19, 0x36, 0xB5, 0xF9, 0x58, 0x28, 0xB9, 0x2E, 0xB7, 0x29, 0x73, 0xC1, 0x59, 0x0A, 0xEB, 0x7A, 0x55, 0x2C, 0xEC, 0xA1, 0x0B, 0x00, 0xC3, 0x03, 0xB7, 0xC7, 0x5D, 0x40, 0x20, 0x71, 0xA7, 0x9E, 0x2C, 0x81, 0x0A, 0xF7, 0xC7, 0x45, 0xE3, 0x33, 0x67, 0x12, 0x49, 0x2A, 0x42, 0x04, 0x3F, 0x29, 0x03, 0xA3, 0x7C, 0x64, 0x34, 0xCE, 0xE2, 0x0B, 0x1D, 0x15, 0x9B, 0x05, 0x76, 0x99, 0xFF, 0x9C, 0x1D, 0x3B, 0xD6, 0x80, 0x29, 0x83, 0x9A, 0x08, 0xF4, 0x3E, 0x6C, 0x1C, 0x81, 0x99, 0x13, 0x53, 0x2F, 0x91, 0x1D, 0xD3, 0x70, 0xC7, 0x02, 0x14, 0x88, 0xE1, 0x1C, 0xB5, 0x04, 0xCB, 0x9C, 0x70, 0x57, 0x0F, 0xFF, 0x35, 0xB4, 0xB4, 0x60, 0x11, 0x91, 0xDC, 0x1A, 0xD9, 0xE6, 0xAD, 0xC5, 0xFA, 0x96, 0x18, 0x79, 0x8D, 0x7C, 0xC8, 0x60, 0xC8, 0x7A, 0x93, 0x9E, 0x4C, 0xCF, 0x85, 0x33, 0x63, 0x22, 0x68, 0xCF, 0x1A, 0x51, 0xAF, 0xF0, 0xCB, 0x81, 0x1C, 0x55, 0x45, 0xCB, 0x16, 0x56, 0xE6, 0x52, 0x69, 0x47, 0x74, 0x30, 0x69, 0x9C, 0xCD, 0xEA, 0x38, 0x00, 0x63, 0x0B, 0x78, 0xCD, 0x58, 0x10, 0x33, 0x4C, 0xCF, 0x02, 0xE0, 0x13, 0xF3, 0xB8, 0x02, 0x44, 0xE7, 0x0A, 0xCD, 0xB0, 0x60, 0xBB, 0xE7, 0xA5, 0x53, 0xB0, 0x63, 0x45, 0x6B, 0x2E, 0xA8, 0x07, 0x47, 0x34, 0x13, 0x16, 0x5C, 0xE5, 0x7D, 0xD5, 0x63, 0x47, 0x3C, 0xFB, 0xC9, 0x06, 0x18, 0xAD, 0xE1, 0xF0, 0xB8, 0x88, 0xAA, 0x48, 0xE7, 0x22, 0xBB, 0x27, 0x51, 0x85, 0x8F, 0xE1, 0x96, 0x87, 0x44, 0x2A, 0x48, 0xE7, 0xCA, 0x0D, 0x2A, 0x29, 0xCD, 0x51, 0xBF, 0xD8, 0xF7, 0x8C, 0x17, 0xB9, 0x66, 0x0B, 0xFB, 0x54, 0xA4, 0x70, 0xB2, 0xAE, 0x9A, 0x95, 0x5C, 0x6A, 0xB8, 0xD6, 0xE5, 0xCC, 0x92, 0xAC, 0x8E, 0xD3, 0xC1, 0x85, 0xDA, 0xA8, 0xBC, 0x29, 0xF0, 0x57, 0x8E, 0xBB, 0x81, 0x2B, 0x97, 0xC9, 0xE5, 0xA8, 0x48, 0xA6, 0x38, 0x4D, 0xE4, 0xE7, 0x5A, 0x31, 0x47, 0x0B, 0x53, 0x06, 0x6A, 0x8D, 0x02, 0x7B, 0xA4, 0x4B, 0x21, 0x74, 0x9C, 0x04, 0x92, 0x46, 0x5F, 0x90, 0x72, 0xB2, 0x83, 0x76, 0xC4, 0xE2, 0x90, 0xB3, 0x0C, 0x18, 0x63, 0xF9, 0xE5, 0xB7, 0x99, 0x96, 0x08, 0x34, 0x22, 0xBD, 0x8C, 0x27, 0x2C, 0x10, 0xEC, 0xC6, 0xEB, 0x9A, 0x0A, 0x82, 0x25, 0xB3, 0x1A, 0xA0, 0xA6, 0x6E, 0x35, 0xB9, 0xC0, 0xB9, 0xA7, 0x95, 0x82, 0xBA, 0x20, 0xA3, 0xC0, 0x4C, 0xD2, 0x99, 0x14, 0xF0, 0x83, 0xA0, 0x15, 0x82, 0x88, 0xBA, 0x4D, 0x6E, 0xB6, 0x2D, 0x87, 0x26, 0x4B, 0x91, 0x2B, 0xCA, 0x39, 0x73, 0x2F, 0xBD, 0xE5, 0x36, 0xA3, 0x77, 0xAD, 0x02, 0xB8, 0xC8, 0x35, 0xD4, 0xA2, 0xF4, 0xE7, 0xB1, 0xCE, 0x11, 0x5D, 0x0C, 0x86, 0x0B, 0xEA, 0xA7, 0x95, 0x5A, 0x49, 0xAD, 0x68, 0x95, 0x86, 0xA8, 0x9A, 0x2B, 0x9F, 0x9B, 0x10, 0xD1, 0x59, 0x5D, 0x2F, 0xC0, 0x65, 0xAD, 0x01, 0x8A, 0x7D, 0x56, 0xC6, 0x14, 0x47, 0x1F, 0x8E, 0x94, 0x6F, 0xE8, 0xAB, 0x49, 0xE8, 0x22, 0x65, 0x91, 0x11, 0x9F, 0xCA, 0xDB, 0x4F, 0x9A, 0x86, 0x16, 0x31, 0x37, 0x87, 0x36, 0xB6, 0x68, 0x8B, 0x78, 0x2D, 0x58, 0xE9, 0x7E, 0x45, 0x72, 0x75, 0x3A, 0x96, 0x64, 0xB6, 0xB8, 0x53, 0x68, 0x12, 0xB2, 0x59, 0x11, 0xAA, 0x76, 0xA2, 0x42, 0x37, 0x54, 0x33, 0x19, 0x27, 0x38, 0xEE, 0xE7, 0x62, 0xF6, 0xB8, 0x43, 0x15, 0xBB, 0x34, 0x36, 0x23, 0x1E, 0x0A, 0x9B, 0x27, 0x7E, 0xD2, 0x8A, 0xE0, 0x05, 0x07, 0x28, 0x34, 0x64, 0x57, 0xE1, 0x34, 0x05, 0x06, 0x2D, 0xB2, 0x80, 0x4B, 0x8D, 0xA6, 0x0B, 0xB5, 0xC7, 0x93, 0xD4, 0xCC, 0x0E, 0x10, 0x1C, 0xBA, 0x2D, 0x91, 0x82, 0xFD, 0x71, 0x24, 0xFF, 0x52, 0xBF, 0x4C, 0xA2, 0x82, 0x92, 0xAC, 0x26, 0xD6, 0x78, 0x08, 0x89, 0x53, 0x97, 0x1D, 0xBA, 0x0B, 0x6F, 0xEC, 0x2C, 0x96, 0x59, 0x35, 0x32, 0x91, 0xC7, 0x0C, 0x5B, 0x92, 0x45, 0xA0, 0xCA, 0x25, 0x33, 0x04, 0xAF, 0xD3, 0xC9, 0x51, 0x02, 0xBE, 0xA6, 0x68, 0x75, 0xC6, 0x20, 0x16, 0x80, 0xB4, 0xBD, 0xA3, 0x86, 0x87, 0xB6, 0x48, 0xC2, 0x8E, 0xB3, 0x74, 0x78, 0xE3, 0xBC, 0x00, 0xCA, 0x8A, 0x3C, 0xC2, 0x72, 0x04, 0x64, 0x2B, 0x42, 0xB6, 0x8F, 0xCB, 0xE7, 0xB2, 0x1A, 0x36, 0x6D, 0x06, 0x68, 0xA5, 0x02, 0x9A, 0x7D, 0xEE, 0xF9, 0x4C, 0xDD, 0x6A, 0x95, 0xD7, 0xEA, 0x89, 0x31, 0x67, 0x3B, 0xF7, 0x11, 0x2D, 0x40, 0x42, 0x10, 0x7B, 0x1B, 0x8B, 0x97, 0x00, 0xC9, 0x74, 0xF9, 0xC4, 0xE8, 0x3A, 0x8F, 0xAC, 0xD8, 0x9B, 0xFE, 0x0C, 0xA3, 0xCC, 0x4C, 0x2F, 0xCE, 0x80, 0xA0, 0x3D, 0x35, 0x76, 0xC2, 0x22, 0xA7, 0x92, 0xB7, 0x2B, 0x1F, 0x07, 0x0A, 0xB7, 0xF6, 0xB6, 0xF2, 0xB5, 0xCA, 0x2A, 0xF5, 0x05, 0x4A, 0xFA, 0x70, 0xA8, 0x96, 0x99, 0x01, 0x59, 0xB4, 0x5D, 0x10, 0x03, 0xE2, 0xA0, 0x56, 0x48, 0x67, 0x5E, 0x59, 0x60, 0x16, 0xF1, 0xB7, 0x1D, 0xD0, 0xF7, 0xBD, 0xA7, 0xE2, 0x09, 0x7F, 0xC7, 0x3B, 0x3A, 0x14, 0x3D, 0x12, 0xC7, 0x26, 0x02, 0x0A, 0xC3, 0x49, 0x58, 0xAD, 0x70, 0x62, 0xB9, 0x2B, 0x9A, 0xBF, 0x3C, 0xA6, 0xBE, 0x5A, 0xE2, 0x9F, 0x57, 0x13, 0x5E, 0x62, 0x5A, 0x36, 0x79, 0x71, 0x83, 0x7E, 0x63, 0x63, 0xD1, 0x53, 0x20, 0x94, 0xE0, 0x22, 0xA2, 0x34, 0x67, 0xCF, 0x93, 0x2E, 0x1F, 0x89, 0xB5, 0xB0, 0x80, 0x3C, 0x1E, 0xC9, 0x9B, 0x58, 0x5A, 0x78, 0xB5, 0x86, 0x50, 0x96, 0x74, 0x6F, 0x32, 0x25, 0x82, 0x14, 0xEC, 0xB3, 0x80, 0x65, 0xC9, 0x7F, 0x45, 0x5E, 0x15, 0x5A, 0xCC, 0x2D, 0xD0, 0x05, 0xA9, 0xC7, 0x6B, 0xED, 0x59, 0xCD, 0xA7, 0x38, 0x37, 0xD3, 0x03, 0x50, 0x4E, 0x6C, 0x97, 0x6A, 0x60, 0x6A, 0x2B, 0xE7, 0xBB, 0xEC, 0x59, 0x48, 0xB9, 0x1A, 0x34, 0x9E, 0x89, 0x36, 0x68, 0x8C, 0xC0, 0x27, 0x97, 0x54, 0xB7, 0x43, 0xAB, 0xC5, 0x86, 0x66, 0xB1, 0x9B, 0x6C, 0x32, 0x60, 0x05, 0x1F, 0x19, 0x20, 0x6B, 0xB9, 0x62, 0xBB, 0x66, 0x33, 0xEB, 0x00, 0x48, 0xE3, 0x2B, 0xAA, 0xCC, 0x5B, 0x02, 0x0D, 0x02, 0xC8, 0x6C, 0xA9, 0x77, 0x0A, 0xD4, 0x69, 0xDB, 0x54, 0xA1, 0x06, 0xAC, 0x73, 0xA3, 0x5B, 0x80, 0x57, 0x42, 0x2B, 0x3D, 0xB2, 0x02, 0xC5, 0xA5, 0xB4, 0xE3, 0xD5, 0x35, 0xF0, 0xFC, 0x99, 0x32, 0x6C, 0x4B, 0x8B, 0x7B, 0x16, 0xF1, 0xCB, 0x5A, 0xF9, 0x68, 0x03, 0xFA, 0x8C, 0x19, 0x5F, 0xC0, 0xBC, 0xED, 0xDA, 0xAF, 0x01, 0x2A, 0x51, 0x72, 0x8B, 0x76, 0x48, 0x90, 0x82, 0x37, 0x3C, 0x91, 0xE9, 0x2C, 0x87, 0xAC, 0xCA, 0x79, 0x51, 0x60, 0x78, 0x2E, 0x3B, 0x0D, 0xD6, 0x43, 0x54, 0x4B, 0xB9, 0x6A, 0xBC, 0x27, 0x08, 0xD4, 0x9B, 0x75, 0x9C, 0xF0, 0x57, 0xAA, 0x22, 0x3B, 0xAF, 0xD9, 0x6A, 0x33, 0x0B, 0xAF, 0x39, 0x81, 0x0F, 0xE8, 0x67, 0x1B, 0x43, 0x43, 0xC2, 0x97, 0xDA, 0x1E, 0x19, 0x69, 0xC9, 0x96, 0x21, 0x6A, 0xB5, 0x10, 0x6D, 0xA6, 0x68, 0x94, 0x1B, 0x16, 0x0D, 0x44, 0x77, 0x01, 0x71, 0x36, 0xCB, 0xCA, 0x5B, 0x5A, 0x8D, 0x44, 0xC4, 0xA8, 0xB1, 0xCF, 0x3E, 0xF7, 0x97, 0x85, 0xE5, 0xAA, 0x25, 0xC3, 0xA1, 0xAD, 0x6C, 0x24, 0xFD, 0x14, 0x0F, 0x79, 0x20, 0x7D, 0xE5, 0xA4, 0x99, 0xF8, 0xA1, 0x53, 0x4F, 0xFA, 0x80, 0x4A, 0xA7, 0xB3, 0x88, 0x9C, 0xBE, 0x25, 0xC0, 0x41, 0x47, 0x04, 0xAA, 0x57, 0x89, 0x7F, 0x17, 0x86, 0x23, 0x64, 0xEC, 0xA5, 0x62, 0x58, 0x00, 0x72, 0x48, 0x81, 0x39, 0x12, 0xB8, 0x36, 0x49, 0x7F, 0x03, 0x59, 0xC2, 0xF7, 0x23, 0x8A, 0x05, 0xD3, 0x05, 0xA0, 0xEA, 0x15, 0x2E, 0x72, 0xB4, 0x44, 0x17, 0xA8, 0x68, 0x13, 0x4E, 0x91, 0xB3, 0xCA, 0x79, 0x31, 0x23, 0x2F, 0xD4, 0xC2, 0x5F, 0x8C, 0x2A, 0x49, 0x2A, 0x33, 0x9C, 0xDC, 0x0A, 0x13, 0x89, 0x67, 0x21, 0x14, 0x51, 0xF2, 0x56, 0x26, 0x78, 0xFA, 0x14, 0x08, 0x0A, 0x34, 0x43, 0x6C, 0x42, 0xB0, 0x78, 0x65, 0xAC, 0x03, 0x6A, 0x81, 0xE9, 0x7A, 0x77, 0x87, 0xA9, 0x38, 0x02, 0x5C, 0xAF, 0x81, 0x34, 0x50, 0x36, 0x8B, 0xED, 0x0C, 0x94, 0xB1, 0x85, 0x76, 0x04, 0x52, 0x64, 0x05, 0xD2, 0x7A, 0x1C, 0x1A, 0xBC, 0x81, 0xB5, 0xB6, 0xEC, 0x13, 0xC7, 0x19, 0x30, 0xA9, 0x7D, 0x92, 0x32, 0xCF, 0x70, 0x21, 0xEF, 0x87, 0xA4, 0xD1, 0x55, 0x32, 0x8E, 0x62, 0xB5, 0x83, 0xA8, 0x3B, 0x4A, 0xF2, 0x1F, 0x9F, 0x57, 0x50, 0xF8, 0x57, 0x51, 0x50, 0x42, 0x4F, 0x63, 0xB8, 0x99, 0xD7, 0x1C, 0xAD, 0x26, 0x7C, 0x09, 0xE4, 0x46, 0x71, 0x46, 0xE1, 0x6E, 0x9B, 0x6C, 0x65, 0x3F, 0x00, 0x8C, 0x31, 0x13, 0x75, 0xE2, 0xE0, 0x06, 0xD4, 0x07, 0x6A, 0x54, 0x6B, 0x82, 0xF5, 0x31, 0x42, 0x22, 0xF7, 0xC6, 0x54, 0x31, 0x7E, 0x79, 0xEC, 0x60, 0x35, 0xB7, 0x3F, 0xAF, 0x49, 0x17, 0x57, 0xE6, 0x1C, 0x82, 0x83, 0x26, 0xD5, 0x30, 0x44, 0x54, 0x1C, 0x4D, 0x45, 0x37, 0xAB, 0xD3, 0xEA, 0x1E, 0x67, 0x99, 0x8C, 0x33, 0x82, 0x97, 0x4C, 0xA7, 0x8A, 0xE1, 0xB1, 0x96, 0x0E, 0x4A, 0x92, 0x26, 0xB0, 0x21, 0x9A, 0xB0, 0x70, 0xF0, 0xD7, 0xAA, 0x66, 0xD7, 0x6F, 0x93, 0x16, 0xAD, 0xB8, 0x0C, 0x54, 0xD6, 0x49, 0x97, 0x71, 0xB4, 0x71, 0xE8, 0x16, 0x8D, 0x47, 0xBC, 0xAA, 0x08, 0x32, 0x4A, 0xB6, 0xBA, 0x92, 0xC3, 0xA7, 0x02, 0x75, 0xF2, 0x4F, 0xA4, 0xDC, 0x10, 0xE2, 0x51, 0x63, 0x3F, 0xB9, 0x8D, 0x16, 0x2B, 0xB5, 0x53, 0x72, 0x02, 0xC6, 0xA5, 0x53, 0xCE, 0x78, 0x41, 0xC4, 0xD4, 0x0B, 0x87, 0x3B, 0x85, 0xCA, 0x03, 0xA0, 0xA1, 0xE1, 0xCF, 0xAD, 0xE6, 0xBA, 0x51, 0x80, 0xAB, 0x13, 0x23, 0xCC, 0xBA, 0x9A, 0x3E, 0x9C, 0x53, 0xD3, 0x75, 0x75, 0xAB, 0x1F, 0xD9, 0xE7, 0x31, 0x6C, 0x6F, 0xEE, 0xCB, 0x0A, 0x14, 0xDF, 0x6F, 0x2D, 0xA5, 0x6C, 0x2F, 0x56, 0xF5, 0x5A, 0x89, 0x63, 0x5C, 0xFC, 0xFD, 0xA4, 0x79, 0x27, 0xAF, 0x1F, 0x0A, 0x47, 0xB2, 0xD4, 0xE4, 0xE6, 0x16, 0x34, 0xB1, 0xB5, 0x1D, 0x37, 0xA3, 0xA3, 0x07, 0xA9, 0x72, 0x42, 0x0D, 0xE1, 0xB7, 0xA4, 0x81, 0xB8, 0x3E, 0x58, 0x3B, 0x6A, 0xF1, 0x6F, 0x63, 0xCB, 0x00, 0xC6}; +std::vector<uint8_t> ct_MLKEM1024 = {0x4F, 0x90, 0x10, 0x6F, 0xF7, 0xC3, 0xDC, 0x4E, 0x47, 0x41, 0x7F, 0x31, 0xAB, 0x56, 0xB1, 0xC5, 0xE4, 0x26, 0xC1, 0xEC, 0xD5, 0x87, 0x8A, 0xAD, 0x2B, 0x70, 0x5E, 0x75, 0x06, 0x2D, 0xA5, 0xFA, 0x6F, 0x4D, 0x18, 0xB7, 0x04, 0xC9, 0x41, 0xC6, 0xC6, 0xD9, 0x41, 0xFD, 0x21, 0x19, 0x1A, 0x69, 0x21, 0x0B, 0xC3, 0x9E, 0x24, 0x95, 0x0D, 0x9F, 0x85, 0x1B, 0x6D, 0xE8, 0xCE, 0x30, 0x02, 0x3D, 0xC7, 0x53, 0x64, 0x39, 0x10, 0x4D, 0x42, 0x24, 0x5F, 0x3E, 0x04, 0xE6, 0xAA, 0x67, 0x63, 0xF8, 0xAC, 0x97, 0xAD, 0xBD, 0x04, 0xCC, 0x69, 0x54, 0x7B, 0xCE, 0x0B, 0xF2, 0x90, 0xFF, 0xB5, 0xD1, 0x29, 0x46, 0x30, 0x11, 0x74, 0xAF, 0x1B, 0x08, 0x68, 0xC1, 0x4D, 0x42, 0x93, 0xFA, 0x9D, 0xCC, 0x5B, 0x23, 0xF8, 0x09, 0xB0, 0x2C, 0xC7, 0x8D, 0xEF, 0xE7, 0xF2, 0x79, 0x35, 0xB9, 0xB6, 0x81, 0xE5, 0x31, 0xFC, 0x21, 0xCC, 0xB2, 0xAF, 0x8E, 0xF6, 0x14, 0x4D, 0x84, 0x98, 0xE6, 0x3E, 0x0E, 0xE4, 0x8A, 0xF8, 0xD4, 0xCE, 0xF7, 0xAC, 0x1F, 0x66, 0x9A, 0xC7, 0x40, 0xB0, 0x6F, 0x79, 0xDD, 0xB5, 0x8E, 0x79, 0x4F, 0x2F, 0xC2, 0xCA, 0x83, 0x2E, 0x05, 0xA0, 0x37, 0x4C, 0x18, 0xA4, 0xF2, 0xCC, 0x78, 0x34, 0x3E, 0xEA, 0x06, 0x4A, 0xBC, 0x5F, 0x46, 0x8F, 0x4D, 0xD1, 0x1E, 0x0B, 0x6E, 0x8F, 0xA1, 0xD1, 0x8A, 0x22, 0x1D, 0x82, 0x41, 0x45, 0x0C, 0x05, 0xEB, 0x9E, 0xDF, 0x90, 0xD9, 0xD7, 0xF6, 0x66, 0xAC, 0x82, 0xE7, 0xFD, 0x44, 0xAF, 0x93, 0x28, 0xE0, 0xBC, 0x60, 0x04, 0xD5, 0xB1, 0x14, 0xE8, 0x0E, 0x9B, 0x98, 0x0D, 0x18, 0xE0, 0x81, 0xD7, 0x71, 0xDF, 0xCB, 0x2A, 0xCF, 0xD4, 0x01, 0x42, 0xA2, 0xEB, 0x33, 0x23, 0x4F, 0x75, 0x73, 0x3E, 0xAB, 0x7D, 0x8E, 0xE8, 0xA5, 0xA6, 0xF7, 0x96, 0x68, 0x1A, 0x4A, 0x8A, 0xF8, 0x5C, 0xCE, 0x86, 0x97, 0x1B, 0x82, 0x1D, 0x4A, 0xD8, 0x37, 0x10, 0x49, 0xE9, 0x4E, 0x28, 0x0B, 0x77, 0xB1, 0x5D, 0x11, 0x1A, 0x42, 0xAE, 0xAD, 0xFC, 0x08, 0xD4, 0xF8, 0x04, 0xBD, 0x78, 0x88, 0x54, 0x43, 0xE8, 0x1A, 0x39, 0x3D, 0xF7, 0xC8, 0x75, 0x4C, 0x46, 0x09, 0x15, 0x84, 0x6E, 0x09, 0xA0, 0x59, 0x65, 0x87, 0x46, 0x00, 0x38, 0xF5, 0x5D, 0x06, 0xEC, 0x21, 0x43, 0x4A, 0x1C, 0x2D, 0xF4, 0x4D, 0x0C, 0x16, 0x70, 0x6E, 0x8D, 0x2B, 0x83, 0xF0, 0xE7, 0x83, 0x39, 0x76, 0xEF, 0x05, 0xBF, 0x1D, 0x9F, 0x0D, 0xDC, 0x9A, 0x37, 0x59, 0x7E, 0x40, 0x1B, 0x81, 0x7C, 0x2B, 0xEC, 0x8E, 0x02, 0xEB, 0x9D, 0xF7, 0x59, 0x1E, 0x23, 0x9F, 0x25, 0xF8, 0x64, 0x8E, 0x7F, 0x2F, 0x4F, 0x67, 0x30, 0x93, 0xBD, 0x9C, 0xB7, 0x03, 0xDA, 0x32, 0xB3, 0x53, 0xF5, 0x85, 0x14, 0xC6, 0xAB, 0x55, 0x74, 0x8B, 0x19, 0x4E, 0x52, 0xF1, 0x53, 0xD5, 0x2F, 0x5F, 0x33, 0xFE, 0x95, 0xC5, 0xF9, 0xF6, 0x5E, 0xA9, 0x7B, 0xA7, 0x21, 0xE8, 0xDD, 0xF3, 0x33, 0xB6, 0x4D, 0x23, 0x3A, 0x86, 0x7A, 0x12, 0x70, 0x1E, 0x00, 0xC5, 0xD8, 0xA9, 0xB5, 0xAE, 0x34, 0x4F, 0x3D, 0x84, 0x7C, 0x27, 0xC0, 0x79, 0xDC, 0xC9, 0xC3, 0xB4, 0x0E, 0xC4, 0x60, 0x4A, 0x9F, 0x04, 0x1E, 0x79, 0x87, 0xE8, 0xB9, 0x30, 0xC6, 0x58, 0xB9, 0xA1, 0x32, 0xDE, 0x4E, 0x42, 0x2C, 0x0E, 0x27, 0x55, 0x3A, 0x2A, 0x0E, 0xAB, 0x8C, 0x85, 0x9E, 0xB0, 0xE5, 0x67, 0x7E, 0x83, 0x27, 0x27, 0x25, 0xC5, 0xC1, 0x65, 0x2E, 0x61, 0xB9, 0xBB, 0xF5, 0xC9, 0xC5, 0x9B, 0xC2, 0x35, 0x7A, 0x4D, 0x1D, 0xB9, 0xC6, 0x07, 0xF3, 0x4D, 0xC1, 0xBA, 0x07, 0x4B, 0x84, 0xDF, 0xC6, 0x9E, 0x40, 0x97, 0xA7, 0xAD, 0x2B, 0xA9, 0xA5, 0x80, 0x00, 0x02, 0x72, 0x96, 0xAD, 0x39, 0xFC, 0x1C, 0xE2, 0x18, 0xA5, 0xEE, 0xC7, 0xAD, 0xFA, 0x8A, 0xA3, 0xB9, 0x10, 0x0B, 0x0B, 0x60, 0x3C, 0xFC, 0x83, 0xC1, 0x52, 0x58, 0x9E, 0x12, 0xE6, 0xBD, 0x9E, 0xE1, 0x0C, 0x49, 0x13, 0x1A, 0x70, 0x1D, 0x31, 0x5D, 0xFE, 0xC3, 0x8E, 0x01, 0x83, 0x28, 0x91, 0x6F, 0x9F, 0xFA, 0xA7, 0x30, 0x5C, 0xFB, 0x66, 0x78, 0x17, 0x07, 0xD2, 0xD1, 0x02, 0x0E, 0xB7, 0x82, 0xF9, 0xF0, 0x03, 0xDB, 0x4E, 0x46, 0xB8, 0x7D, 0x69, 0x3F, 0x62, 0xE8, 0xBD, 0xE1, 0x70, 0x14, 0x1F, 0xF7, 0x1F, 0x26, 0xDD, 0xF5, 0x31, 0x0C, 0x00, 0xC9, 0x16, 0x36, 0x55, 0xF5, 0x21, 0x7D, 0xD2, 0xC8, 0xB0, 0x46, 0x6A, 0xC8, 0x9D, 0xB5, 0x5B, 0xD7, 0xFB, 0x3B, 0x09, 0x64, 0xBC, 0x90, 0x09, 0xE9, 0x68, 0x61, 0x85, 0x11, 0x7D, 0xCB, 0x50, 0xD6, 0xD0, 0x29, 0x77, 0x53, 0xCF, 0x7F, 0x12, 0x17, 0xE8, 0x19, 0xEE, 0x60, 0xE3, 0xF0, 0xFA, 0xEC, 0x4A, 0x5A, 0xF0, 0xC2, 0xEA, 0x83, 0xCC, 0xDE, 0x15, 0xCF, 0x04, 0x5C, 0x69, 0x61, 0xDE, 0x8F, 0xF6, 0x23, 0x5C, 0x9D, 0x93, 0xBA, 0x4C, 0x89, 0xB7, 0xA8, 0x2A, 0x74, 0x71, 0xFC, 0xFB, 0x0B, 0x8E, 0xAD, 0x54, 0xD5, 0x6E, 0x8A, 0x1D, 0xE2, 0x1B, 0x39, 0x33, 0xAC, 0x5B, 0x4A, 0x06, 0x89, 0xEE, 0xF3, 0x59, 0x89, 0x26, 0xE1, 0x7B, 0xBB, 0x16, 0xAE, 0xC6, 0x1E, 0xC3, 0x0A, 0x2C, 0xCC, 0x0E, 0x03, 0x23, 0xEC, 0x28, 0x28, 0x87, 0xC1, 0x08, 0xC3, 0xA4, 0xE8, 0x3E, 0x36, 0x66, 0x49, 0x3D, 0x86, 0x53, 0xD0, 0xE9, 0x24, 0x43, 0x80, 0x8C, 0x79, 0xD7, 0x70, 0xBF, 0xF4, 0x8A, 0x49, 0xE6, 0x5A, 0xE0, 0x89, 0xFE, 0xC7, 0x90, 0xBB, 0xA4, 0xC6, 0x63, 0x54, 0xEF, 0x67, 0xA3, 0x34, 0xC1, 0xEA, 0x5C, 0x6C, 0x57, 0x07, 0xB6, 0x92, 0x8E, 0xBD, 0x1B, 0xDB, 0x6A, 0x94, 0x0F, 0xA2, 0x42, 0xC6, 0xEB, 0xD7, 0xF3, 0xE7, 0x12, 0x72, 0x42, 0x1C, 0x90, 0x82, 0x84, 0x1A, 0x6C, 0xAD, 0x28, 0x94, 0xBB, 0x8A, 0xC8, 0x5F, 0x10, 0x5D, 0x8B, 0xBC, 0x9E, 0x6F, 0x0A, 0x3D, 0xF0, 0xD7, 0xC4, 0x6F, 0x6E, 0x2F, 0x4C, 0xAB, 0x90, 0x4E, 0xD1, 0x57, 0xAF, 0xA8, 0x5D, 0x4A, 0x85, 0x22, 0x20, 0xA9, 0x63, 0x6E, 0x1E, 0x88, 0x21, 0x64, 0x3A, 0x9E, 0x40, 0x28, 0xD8, 0x7A, 0x43, 0x04, 0x32, 0xF0, 0x93, 0x54, 0xB3, 0x97, 0x31, 0x82, 0x38, 0x5C, 0xF5, 0xAB, 0xFC, 0x8F, 0x84, 0x98, 0x2B, 0xEE, 0x0B, 0xCB, 0xF5, 0xD1, 0x86, 0x37, 0x39, 0x91, 0x63, 0xA0, 0x9E, 0xB4, 0x57, 0x11, 0xE0, 0x7C, 0x44, 0x58, 0x49, 0x8C, 0x76, 0x97, 0x91, 0x07, 0xCF, 0x91, 0xB3, 0xFC, 0x59, 0x0E, 0xA4, 0xAD, 0x71, 0x5D, 0x65, 0x6D, 0x5E, 0x56, 0xDC, 0x32, 0x14, 0x65, 0x80, 0x10, 0x1C, 0x95, 0x2E, 0x02, 0xED, 0x70, 0x17, 0x96, 0x0D, 0x54, 0xCA, 0xAC, 0xCC, 0x70, 0x60, 0x71, 0x96, 0x98, 0x0A, 0xDB, 0xDA, 0xEA, 0x42, 0x0A, 0x52, 0xC0, 0x55, 0x9E, 0xD2, 0x3C, 0x95, 0x14, 0xF8, 0xCA, 0x7A, 0xB7, 0xF3, 0xBA, 0xAF, 0xD2, 0xFA, 0xB5, 0x89, 0x60, 0xA6, 0x41, 0x28, 0xD5, 0xA5, 0x0E, 0x9A, 0xD8, 0xDB, 0x7D, 0x23, 0xA9, 0x0C, 0xE6, 0x4C, 0x1B, 0xC3, 0x49, 0xD1, 0x18, 0xD3, 0x60, 0x33, 0x58, 0x37, 0x7F, 0x84, 0xFF, 0x5A, 0x64, 0x45, 0x7F, 0xA1, 0xCF, 0x41, 0xB2, 0x70, 0x94, 0xBC, 0xA7, 0x23, 0x60, 0xBD, 0x42, 0x94, 0x15, 0xB9, 0xEF, 0x9A, 0xCC, 0xB7, 0xA5, 0xD7, 0xB9, 0xE5, 0xF5, 0xFD, 0xCA, 0x8F, 0xCF, 0xA4, 0x59, 0x2E, 0x91, 0xD7, 0xE5, 0x12, 0x0D, 0xF7, 0xE3, 0xC6, 0x67, 0x5A, 0xF2, 0x21, 0x1B, 0xB9, 0x4D, 0x85, 0x6A, 0x5D, 0x22, 0x85, 0xFB, 0xBB, 0x36, 0x98, 0x4A, 0x13, 0x45, 0x59, 0x09, 0x30, 0xB1, 0x32, 0x32, 0x56, 0x5D, 0x54, 0x81, 0x2A, 0x93, 0x45, 0x32, 0x4C, 0x23, 0x26, 0x53, 0x19, 0x03, 0x23, 0xCC, 0x67, 0xC8, 0x40, 0xE4, 0x78, 0xD0, 0x9E, 0x6D, 0xDB, 0xCF, 0x99, 0x9F, 0x7A, 0xA3, 0xB5, 0x56, 0xF8, 0x03, 0x32, 0xE6, 0x7A, 0xCA, 0x41, 0xEC, 0x06, 0x61, 0x08, 0x8D, 0x76, 0x96, 0xBB, 0x64, 0xE9, 0xA9, 0x8A, 0x07, 0x49, 0xFA, 0xA9, 0x85, 0x4D, 0x9B, 0x48, 0x75, 0x40, 0x23, 0xBA, 0xCA, 0xF3, 0xC8, 0x08, 0x1A, 0x46, 0x15, 0x7C, 0x64, 0x53, 0xBD, 0xC8, 0x93, 0x41, 0xD3, 0x09, 0x2F, 0x3B, 0x53, 0x37, 0x87, 0x4C, 0xE5, 0xDE, 0x55, 0x9A, 0x56, 0xA2, 0xFF, 0xB7, 0xF4, 0x01, 0xF6, 0xE2, 0x8E, 0xEC, 0xAF, 0x4F, 0xDE, 0x5B, 0x60, 0xDE, 0xA7, 0x3D, 0x6B, 0x21, 0x82, 0xEF, 0x68, 0xE0, 0x7A, 0x82, 0x97, 0xF3, 0xC9, 0x59, 0xE1, 0x71, 0x39, 0xB5, 0xDE, 0xDC, 0x72, 0xC7, 0xA0, 0xE1, 0x03, 0xAF, 0xF8, 0x66, 0xE8, 0x9D, 0x1F, 0x62, 0xA1, 0xF6, 0xB9, 0x7B, 0x61, 0xBC, 0x05, 0x9B, 0xDE, 0x5A, 0x2A, 0x06, 0x08, 0x7E, 0xF7, 0x83, 0xA4, 0x41, 0xF2, 0x3D, 0xD1, 0x91, 0xC6, 0x92, 0xD0, 0x3C, 0x09, 0x7F, 0xF9, 0xEE, 0x83, 0x1F, 0x77, 0x15, 0xC6, 0xE5, 0x08, 0xBF, 0x47, 0x5E, 0x79, 0xA8, 0x35, 0x3E, 0x84, 0xB0, 0x6A, 0x93, 0x56, 0x04, 0x5C, 0x8F, 0xD0, 0x9F, 0xBA, 0x35, 0x87, 0x90, 0x69, 0xB9, 0xA3, 0xF4, 0x78, 0xFB, 0xD0, 0x51, 0x14, 0x3C, 0x13, 0xD7, 0x53, 0xBC, 0x45, 0xF3, 0x04, 0x0E, 0x85, 0x98, 0x5E, 0xFD, 0x6B, 0x14, 0x9E, 0xFA, 0x94, 0x55, 0xA1, 0x8E, 0x28, 0x94, 0xE6, 0xEA, 0x0B, 0xE5, 0x8F, 0x45, 0x1F, 0xF1, 0x15, 0x6F, 0x93, 0xCC, 0x71, 0x17, 0xB5, 0xD0, 0x91, 0xE9, 0xDD, 0x50, 0xD4, 0x1B, 0xFC, 0xCD, 0x44, 0xF2, 0xC4, 0xEB, 0x78, 0x12, 0xAE, 0xFD, 0x13, 0xC8, 0xB6, 0x8D, 0x7F, 0x01, 0x03, 0xBB, 0x6C, 0xA3, 0x8D, 0x23, 0x3B, 0x6A, 0xAD, 0xD0, 0x18, 0x45, 0xB7, 0xE4, 0x4D, 0x13, 0xC1, 0xCB, 0x15, 0x77, 0xD6, 0xC4, 0x35, 0x4B, 0x06, 0x39, 0x91, 0x34, 0x47, 0x87, 0xF8, 0xC0, 0xBE, 0x66, 0x7A, 0x74, 0x40, 0xB9, 0x89, 0x17, 0xAD, 0x64, 0xCC, 0x2E, 0xF2, 0xBC, 0x82, 0xEF, 0xC3, 0x39, 0x8B, 0x3B, 0x1B, 0x23, 0x85, 0x40, 0x75, 0x6C, 0xE9, 0xFC, 0x5E, 0xDD, 0x26, 0xCC, 0x20, 0xE7, 0x61, 0xD5, 0x92, 0xA1, 0xA0, 0x53, 0x0A, 0xA8, 0xBE, 0xFC, 0xFE, 0x8D, 0xAD, 0xBA, 0xC9, 0x9A, 0x41, 0x7C, 0xA0, 0x82, 0x7F, 0x49, 0x83, 0xFF, 0x5B, 0xE6, 0x56, 0x66, 0x9F, 0x2B, 0x5F, 0x98, 0x5F, 0xF6, 0xB1, 0x6C, 0x44, 0xBB, 0xEA, 0x13, 0x1D, 0x1F, 0xCC, 0x70, 0xFC, 0x53, 0xBF, 0x31, 0xEF, 0x22, 0x5D, 0x1F, 0x5D, 0x41, 0x86, 0x3B, 0x51, 0xB5, 0x7E, 0xA6, 0x5C, 0x61, 0x64, 0xF7, 0x53, 0x1A, 0xE4, 0x92, 0xEF, 0xA6, 0x41, 0x61, 0xB7, 0xDA, 0xBA, 0x3E, 0xF4, 0x58, 0x6F, 0x34, 0x59, 0xBE, 0x8A, 0x96, 0x23, 0x67, 0xDC, 0x27, 0x65, 0x97, 0xB9, 0x8E, 0x91, 0xFF, 0x59, 0x4E, 0xFE, 0x88, 0x49, 0xBA, 0xD4, 0xCF, 0x91, 0xB9, 0xE5, 0xF2, 0x44, 0xCF, 0x03, 0xCA, 0x96, 0x15, 0xBE, 0x12, 0x8E, 0x96, 0x95, 0x85, 0x33, 0x54, 0x4A, 0x56, 0xE7, 0x35, 0x99, 0x4B, 0x92, 0xE4, 0xEF, 0x0D, 0x5F, 0xAB, 0x54, 0xB7, 0x8E, 0xC6, 0x66, 0x41, 0xC7, 0x46, 0x3F, 0x22, 0x5D, 0x26, 0x1C, 0x14, 0x4F, 0x00, 0xA0, 0x27, 0x07, 0x41, 0xD7, 0xA5, 0x11, 0x99, 0x48, 0x33, 0x63, 0x5A, 0x8A, 0x9B, 0x67, 0x0C, 0xBF, 0xBE, 0xF2, 0x39, 0xBF, 0x83, 0x32, 0x7E, 0x24, 0x79, 0x43, 0xB2, 0x05, 0xDA, 0x68, 0xDB, 0x94, 0xE3, 0xF3}; +std::vector<uint8_t> ss_MLKEM1024 = {0x75, 0x45, 0xCC, 0x45, 0x8E, 0x0A, 0x27, 0x4A, 0x83, 0xB1, 0x35, 0x54, 0x22, 0x4F, 0x0B, 0xD0, 0x1D, 0x57, 0xCC, 0x47, 0x75, 0xAD, 0x12, 0x46, 0x8D, 0x3F, 0xEE, 0x5B, 0x08, 0xC9, 0x3A, 0x6A}; diff --git a/tester/lime-tester-utils.cpp b/tester/lime-tester-utils.cpp index 91fc941..1bd4960 100644 --- a/tester/lime-tester-utils.cpp +++ b/tester/lime-tester-utils.cpp @@ -191,7 +191,7 @@ void randomize(uint8_t *buffer, const size_t size) { * if fileName doesn't exists as a DB, it will be created, caller shall then delete it if needed */ template<typename Curve> -void dr_sessionsInit(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage, std::shared_ptr<RNG> RNG_context) { +void dr_sessionsInitImpl(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage, std::shared_ptr<RNG> RNG_context, std::false_type) { if (initStorage==true) { // create or load Db localStorageAlice = std::make_shared<lime::Db>(dbFilenameAlice); @@ -229,8 +229,8 @@ void dr_sessionsInit(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std:: } #ifdef HAVE_BCTBXPQ -template<> -void dr_sessionsInit<C255K512>(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage, std::shared_ptr<RNG> RNG_context) { +template<typename Curve> +void dr_sessionsInitImpl(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage, std::shared_ptr<RNG> RNG_context, std::true_type) { if (initStorage==true) { // create or load Db localStorageAlice = std::make_shared<lime::Db>(dbFilenameAlice); @@ -238,16 +238,16 @@ void dr_sessionsInit<C255K512>(std::shared_ptr<DR> &alice, std::shared_ptr<DR> & } /* generate EC key pair for bob */ - auto tempECDH = make_keyExchange<C255K512::EC>(); + auto tempECDH = make_keyExchange<typename Curve::EC>(); tempECDH->createKeyPair(RNG_context); - Xpair<C255K512::EC> bobECKeyPair{tempECDH->get_selfPublic(), tempECDH->get_secret()}; + Xpair<typename Curve::EC> bobECKeyPair{tempECDH->get_selfPublic(), tempECDH->get_secret()}; /* generate KEM key pair for bob */ - Kpair<C255K512::KEM> bobKEMKeyPair; - auto tempKEM = make_KEM<C255K512::KEM>(); + Kpair<typename Curve::KEM> bobKEMKeyPair; + auto tempKEM = make_KEM<typename Curve::KEM>(); tempKEM->createKeyPair(bobKEMKeyPair); - ARrKey<C255K512> bobPK(bobECKeyPair.publicKey(), bobKEMKeyPair.publicKey()); - ARsKey<C255K512> bobKeyPair(bobECKeyPair, bobKEMKeyPair); + ARrKey<Curve> bobPK(bobECKeyPair.publicKey(), bobKEMKeyPair.publicKey()); + ARsKey<Curve> bobKeyPair(bobECKeyPair, bobKEMKeyPair); /* generate a shared secret and AD */ lime::DRChainKey SK; @@ -269,12 +269,17 @@ void dr_sessionsInit<C255K512>(std::shared_ptr<DR> &alice, std::shared_ptr<DR> & // create DR sessions std::vector<uint8_t> X3DH_initMessage{}; - DSA<C255K512::EC, lime::DSAtype::publicKey> dummyPeerIk{}; // DR session creation gets the peerDeviceId and peerIk but uses it only if peerDid is 0, give dummy, we're focusing on DR here - alice = make_DR_for_sender<C255K512>(localStorageAlice, SK, AD, bobPK, aliceDid, "dummyPeerDevice", dummyPeerIk, aliceUid, X3DH_initMessage, RNG_context); - bob = make_DR_for_receiver<C255K512>(localStorageBob, SK, AD, bobKeyPair, bobDid, "dummyPeerDevice", 0, dummyPeerIk, bobUid, RNG_context); + DSA<typename Curve::EC, lime::DSAtype::publicKey> dummyPeerIk{}; // DR session creation gets the peerDeviceId and peerIk but uses it only if peerDid is 0, give dummy, we're focusing on DR here + alice = make_DR_for_sender<Curve>(localStorageAlice, SK, AD, bobPK, aliceDid, "dummyPeerDevice", dummyPeerIk, aliceUid, X3DH_initMessage, RNG_context); + bob = make_DR_for_receiver<Curve>(localStorageBob, SK, AD, bobKeyPair, bobDid, "dummyPeerDevice", 0, dummyPeerIk, bobUid, RNG_context); } #endif //HAVE_BCTBXPQ +template<typename Curve> +void dr_sessionsInit(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage, std::shared_ptr<RNG> RNG_context) { + using Tag = std::conditional_t<std::is_base_of_v<lime::genericKEM, Curve>, std::true_type, std::false_type>; + dr_sessionsInitImpl<Curve>(alice, bob, localStorageAlice, localStorageBob, dbFilenameAlice, dbFilenameBob, initStorage, RNG_context, Tag{}); +} /** * @brief Create and initialise all requested DR sessions for specified number of devices between two or more users @@ -426,6 +431,42 @@ bool DR_message_holdsX3DHInit(const std::vector<uint8_t> &message, bool &haveOPk haveOPk=true; } return true; + case static_cast<uint8_t>(lime::CurveId::c25519mlk512): + if (message[3] == 0x00) { // no OPk in the X3DH init message + if (payload_direct_encryption) { + if (message.size() <= (23 + X<C255, lime::Xtype::publicKey>::ssize() + K<MLK512, lime::Ktype::publicKey>::ssize() + K<MLK512, lime::Ktype::cipherText>::ssize() + 5 + DSA<C255, lime::DSAtype::publicKey>::ssize() + K<MLK512, lime::Ktype::cipherText>::ssize() + X<C255, lime::Xtype::publicKey>::ssize())) return false; + } else { + if (message.size() != (55 + X<C255, lime::Xtype::publicKey>::ssize() + K<MLK512, lime::Ktype::publicKey>::ssize() + K<MLK512, lime::Ktype::cipherText>::ssize() + 5 + DSA<C255, lime::DSAtype::publicKey>::ssize() + K<MLK512, lime::Ktype::cipherText>::ssize() + X<C255, lime::Xtype::publicKey>::ssize())) return false; + } + haveOPk=false; + } else { // OPk present in the X3DH init message + if (payload_direct_encryption) { + if (message.size() <= (23 + X<C255, lime::Xtype::publicKey>::ssize() + K<MLK512, lime::Ktype::publicKey>::ssize() + K<MLK512, lime::Ktype::cipherText>::ssize() + 9 + DSA<C255, lime::DSAtype::publicKey>::ssize() + K<MLK512, lime::Ktype::cipherText>::ssize() + X<C255, lime::Xtype::publicKey>::ssize())) return false; + } else { + if (message.size() != (55 + X<C255, lime::Xtype::publicKey>::ssize() + K<MLK512, lime::Ktype::publicKey>::ssize() + K<MLK512, lime::Ktype::cipherText>::ssize() + 9 + DSA<C255, lime::DSAtype::publicKey>::ssize() + K<MLK512, lime::Ktype::cipherText>::ssize() + X<C255, lime::Xtype::publicKey>::ssize())) return false; + } + haveOPk=true; + } + return true; + + case static_cast<uint8_t>(lime::CurveId::c448mlk1024): + if (message[3] == 0x00) { // no OPk in the X3DH init message + if (payload_direct_encryption) { + if (message.size() <= (23 + X<C448, lime::Xtype::publicKey>::ssize() + K<MLK1024, lime::Ktype::publicKey>::ssize() + K<MLK1024, lime::Ktype::cipherText>::ssize() + 5 + DSA<C448, lime::DSAtype::publicKey>::ssize() + K<MLK1024, lime::Ktype::cipherText>::ssize() + X<C448, lime::Xtype::publicKey>::ssize())) return false; + } else { + if (message.size() != (55 + X<C448, lime::Xtype::publicKey>::ssize() + K<MLK1024, lime::Ktype::publicKey>::ssize() + K<MLK1024, lime::Ktype::cipherText>::ssize() + 5 + DSA<C448, lime::DSAtype::publicKey>::ssize() + K<MLK1024, lime::Ktype::cipherText>::ssize() + X<C448, lime::Xtype::publicKey>::ssize())) return false; + } + haveOPk=false; + } else { // OPk present in the X3DH init message + if (payload_direct_encryption) { + if (message.size() <= (23 + X<C448, lime::Xtype::publicKey>::ssize() + K<MLK1024, lime::Ktype::publicKey>::ssize() + K<MLK1024, lime::Ktype::cipherText>::ssize() + 9 + DSA<C448, lime::DSAtype::publicKey>::ssize() + K<MLK1024, lime::Ktype::cipherText>::ssize() + X<C448, lime::Xtype::publicKey>::ssize())) return false; + } else { + if (message.size() != (55 + X<C448, lime::Xtype::publicKey>::ssize() + K<MLK1024, lime::Ktype::publicKey>::ssize() + K<MLK1024, lime::Ktype::cipherText>::ssize() + 9 + DSA<C448, lime::DSAtype::publicKey>::ssize() + K<MLK1024, lime::Ktype::cipherText>::ssize() + X<C448, lime::Xtype::publicKey>::ssize())) return false; + } + haveOPk=true; + } + return true; + #endif // HAVE_BCTBXPQ default: return false; @@ -442,6 +483,10 @@ size_t DR_Message_X3DHInitSize(uint8_t curveId, bool OPkFlag) { #ifdef HAVE_BCTBXPQ case static_cast<uint8_t>(lime::CurveId::c25519k512): return lime::double_ratchet_protocol::X3DHinitSize<C255K512>(OPkFlag); + case static_cast<uint8_t>(lime::CurveId::c25519mlk512): + return lime::double_ratchet_protocol::X3DHinitSize<C255MLK512>(OPkFlag); + case static_cast<uint8_t>(lime::CurveId::c448mlk1024): + return lime::double_ratchet_protocol::X3DHinitSize<C448MLK1024>(OPkFlag); #endif } return 0; @@ -476,6 +521,12 @@ bool DR_message_extractX3DHInit_SPkId(const std::vector<uint8_t> &message, uint3 case static_cast<uint8_t>(lime::CurveId::c25519k512): SPkIdPos += DSA<C255, lime::DSAtype::publicKey>::ssize() + X<C255, lime::Xtype::publicKey>::ssize() + K<K512, lime::Ktype::cipherText>::ssize(); break; + case static_cast<uint8_t>(lime::CurveId::c25519mlk512): + SPkIdPos += DSA<C255, lime::DSAtype::publicKey>::ssize() + X<C255, lime::Xtype::publicKey>::ssize() + K<MLK512, lime::Ktype::cipherText>::ssize(); + break; + case static_cast<uint8_t>(lime::CurveId::c448mlk1024): + SPkIdPos += DSA<C448, lime::DSAtype::publicKey>::ssize() + X<C448, lime::Xtype::publicKey>::ssize() + K<MLK1024, lime::Ktype::cipherText>::ssize(); + break; #endif } @@ -667,7 +718,16 @@ int wait_for_mutex(belle_sip_stack_t*s1,int* counter,int value,int timeout, std: template void dr_devicesInit<C448>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C448>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles, std::shared_ptr<RNG> RNG_context); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED + template void dr_sessionsInit<C255K512>(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage, std::shared_ptr<RNG> RNG_context); template void dr_devicesInit<C255K512>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C255K512>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles, std::shared_ptr<RNG> RNG_context); -#endif //HAVE_BCTBXPQ + template void dr_sessionsInit<C255MLK512>(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage, std::shared_ptr<RNG> RNG_context); + template void dr_devicesInit<C255MLK512>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C255MLK512>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles, std::shared_ptr<RNG> RNG_context); +#endif +#ifdef EC448_ENABLED + template void dr_devicesInit<C448MLK1024>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C448MLK1024>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles, std::shared_ptr<RNG> RNG_context); + template void dr_sessionsInit<C448MLK1024>(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage, std::shared_ptr<RNG> RNG_context); +#endif +#endif // HAVE_BCTBXPQ } // namespace lime_tester diff --git a/tester/lime-tester-utils.hpp b/tester/lime-tester-utils.hpp index 4b7dc98..de4cf9d 100644 --- a/tester/lime-tester-utils.hpp +++ b/tester/lime-tester-utils.hpp @@ -181,8 +181,18 @@ int wait_for_mutex(belle_sip_stack_t*s1,int* counter,int value,int timeout, std: extern template void dr_devicesInit<C448>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C448>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles, std::shared_ptr<RNG> RNG_context); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED + extern template void dr_sessionsInit<C255K512>(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage, std::shared_ptr<RNG> RNG_context); extern template void dr_devicesInit<C255K512>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C255K512>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles, std::shared_ptr<RNG> RNG_context); + extern template void dr_sessionsInit<C255MLK512>(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage, std::shared_ptr<RNG> RNG_context); + extern template void dr_devicesInit<C255MLK512>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C255MLK512>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles, std::shared_ptr<RNG> RNG_context); +#endif +#ifdef EC448_ENABLED + extern template void dr_devicesInit<C448MLK1024>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C448MLK1024>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles, std::shared_ptr<RNG> RNG_context); + extern template void dr_sessionsInit<C448MLK1024>(std::shared_ptr<DR> &alice, std::shared_ptr<DR> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage, std::shared_ptr<RNG> RNG_context); #endif +#endif // HAVE_BCTBXPQ + } // namespace lime_tester extern "C" { diff --git a/tester/lime_crypto-tester.cpp b/tester/lime_crypto-tester.cpp index 4f0d890..96b99bc 100644 --- a/tester/lime_crypto-tester.cpp +++ b/tester/lime_crypto-tester.cpp @@ -165,19 +165,30 @@ static void exchange(void) { /* get patterns specialized constructor */ template <typename Algo> -void KEM_getPatterns(lime::K<Algo, lime::Ktype::privateKey> &sk, lime::K<Algo, lime::Ktype::publicKey> &pk, lime::K<Algo, lime::Ktype::cipherText> &ct, lime::K<Algo, lime::Ktype::sharedSecret> &ss) { +void KEM_getPatterns(lime::K<Algo, lime::Ktype::privateKey> &sk, lime::K<Algo, lime::Ktype::cipherText> &ct, lime::K<Algo, lime::Ktype::sharedSecret> &ss) { /* if this template is instanciated the static_assert will fail but will give us an error message with faulty Curve type */ static_assert(sizeof(Algo) != sizeof(Algo), "You must specialize KEM class contructor for your type"); } #ifdef HAVE_BCTBXPQ - /* specialise KEM creation : K512 is Kyber512 */ -template <> void KEM_getPatterns<K512>(lime::K<lime::K512, lime::Ktype::privateKey> &sk, lime::K<lime::K512, lime::Ktype::publicKey> &pk, lime::K<lime::K512, lime::Ktype::cipherText> &ct, lime::K<lime::K512, lime::Ktype::sharedSecret> &ss) { +/* specialise KEMpattern creation : K512 is Kyber512 */ +template <> void KEM_getPatterns<K512>(lime::K<lime::K512, lime::Ktype::privateKey> &sk, lime::K<lime::K512, lime::Ktype::cipherText> &ct, lime::K<lime::K512, lime::Ktype::sharedSecret> &ss) { sk.assign(sk_KYBER512.cbegin()); - pk.assign(pk_KYBER512.cbegin()); ct.assign(ct_KYBER512.cbegin()); ss.assign(ss_KYBER512.cbegin()); } +/* specialise KEMpattern creation : MLK512 is MLKEM512 */ +template <> void KEM_getPatterns<MLK512>(lime::K<lime::MLK512, lime::Ktype::privateKey> &sk, lime::K<lime::MLK512, lime::Ktype::cipherText> &ct, lime::K<lime::MLK512, lime::Ktype::sharedSecret> &ss) { + sk.assign(sk_MLKEM512.cbegin()); + ct.assign(ct_MLKEM512.cbegin()); + ss.assign(ss_MLKEM512.cbegin()); +} +/* specialise KEMpattern creation : MLK1024 is MLKEM1024 */ +template <> void KEM_getPatterns<MLK1024>(lime::K<lime::MLK1024, lime::Ktype::privateKey> &sk, lime::K<lime::MLK1024, lime::Ktype::cipherText> &ct, lime::K<lime::MLK1024, lime::Ktype::sharedSecret> &ss) { + sk.assign(sk_MLKEM1024.cbegin()); + ct.assign(ct_MLKEM1024.cbegin()); + ss.assign(ss_MLKEM1024.cbegin()); +} #endif //HAVE_BCTBXPQ template <typename Algo> @@ -204,10 +215,9 @@ void KEM_test(void) { /* Patterns */ lime::K<Algo, lime::Ktype::privateKey> skPattern; - lime::K<Algo, lime::Ktype::publicKey> pkPattern; lime::K<Algo, lime::Ktype::cipherText> ctPattern; lime::K<Algo, lime::Ktype::sharedSecret> ssPattern; - KEM_getPatterns<Algo>(skPattern, pkPattern, ctPattern, ssPattern); + KEM_getPatterns<Algo>(skPattern, ctPattern, ssPattern); Alice->decaps(skPattern, ctPattern, ssAlice); BC_ASSERT_TRUE(ssAlice == ssPattern); @@ -288,6 +298,16 @@ static void keyEncapsulation(void) { LIME_LOGI<<"Bench for Kyber512:"; KEM_bench<K512>(BENCH_TIMING_MS); } + KEM_test<MLK512>(); + if (bench) { + LIME_LOGI<<"Bench for MLKem512:"; + KEM_bench<MLK512>(BENCH_TIMING_MS); + } + KEM_test<MLK1024>(); + if (bench) { + LIME_LOGI<<"Bench for MLKem1024:"; + KEM_bench<MLK1024>(BENCH_TIMING_MS); + } #endif } diff --git a/tester/lime_helloworld-tester.cpp b/tester/lime_helloworld-tester.cpp index 1db4f06..93048cc 100644 --- a/tester/lime_helloworld-tester.cpp +++ b/tester/lime_helloworld-tester.cpp @@ -610,7 +610,13 @@ static void helloworld_basic(void) { helloworld_basic_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED helloworld_basic_test(lime::CurveId::c25519k512); + helloworld_basic_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + helloworld_basic_test(lime::CurveId::c448mlk1024); +#endif #endif } @@ -622,7 +628,13 @@ static void helloworld_verifyIdentity(void) { helloworld_verifyIdentity_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED helloworld_verifyIdentity_test(lime::CurveId::c25519k512); + helloworld_verifyIdentity_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + helloworld_verifyIdentity_test(lime::CurveId::c448mlk1024); +#endif #endif } diff --git a/tester/lime_lime-tester.cpp b/tester/lime_lime-tester.cpp index 8133076..5c10cc7 100644 --- a/tester/lime_lime-tester.cpp +++ b/tester/lime_lime-tester.cpp @@ -390,10 +390,23 @@ static void lime_encryptionPolicyError() { lime_tester::shortMessage, lime::EncryptionPolicy::cipherMessage); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_encryptionPolicyError_test(lime::CurveId::c25519k512, "lime_encryptionPolicyError_DR", lime_tester::shortMessage, lime::EncryptionPolicy::DRMessage); lime_encryptionPolicyError_test(lime::CurveId::c25519k512, "lime_encryptionPolicyError_cipher", lime_tester::shortMessage, lime::EncryptionPolicy::cipherMessage); + + lime_encryptionPolicyError_test(lime::CurveId::c25519mlk512, "lime_encryptionPolicyError_DR", + lime_tester::shortMessage, lime::EncryptionPolicy::DRMessage); + lime_encryptionPolicyError_test(lime::CurveId::c25519mlk512, "lime_encryptionPolicyError_cipher", + lime_tester::shortMessage, lime::EncryptionPolicy::cipherMessage); +#endif +#ifdef EC448_ENABLED + lime_encryptionPolicyError_test(lime::CurveId::c448mlk1024, "lime_encryptionPolicyError_DR", + lime_tester::shortMessage, lime::EncryptionPolicy::DRMessage); + lime_encryptionPolicyError_test(lime::CurveId::c448mlk1024, "lime_encryptionPolicyError_cipher", + lime_tester::shortMessage, lime::EncryptionPolicy::cipherMessage); +#endif #endif } @@ -667,7 +680,14 @@ static void lime_encryptionPolicy() { lime_encryptionPolicy_suite(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_encryptionPolicy_suite(lime::CurveId::c25519k512); + + lime_encryptionPolicy_suite(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_encryptionPolicy_suite(lime::CurveId::c448mlk1024); +#endif #endif } @@ -966,7 +986,14 @@ static void lime_identityVerifiedStatus() { lime_identityVerifiedStatus_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_identityVerifiedStatus_test(lime::CurveId::c25519k512); + + lime_identityVerifiedStatus_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_identityVerifiedStatus_test(lime::CurveId::c448mlk1024); +#endif #endif } @@ -1195,7 +1222,14 @@ static void lime_peerDeviceStatus() { lime_peerDeviceStatus_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_peerDeviceStatus_test(lime::CurveId::c25519k512); + + lime_peerDeviceStatus_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_peerDeviceStatus_test(lime::CurveId::c448mlk1024); +#endif #endif } @@ -1286,7 +1320,14 @@ static void lime_encryptToUnsafe() { lime_encryptToUnsafe_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_encryptToUnsafe_test(lime::CurveId::c25519k512); + + lime_encryptToUnsafe_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_encryptToUnsafe_test(lime::CurveId::c448mlk1024); +#endif #endif } @@ -1955,7 +1996,14 @@ static void lime_update_OPk() { lime_update_OPk_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_update_OPk_test(lime::CurveId::c25519k512); + + lime_update_OPk_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_update_OPk_test(lime::CurveId::c448mlk1024); +#endif #endif } @@ -2121,7 +2169,14 @@ static void lime_update_SPk() { lime_update_SPk_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_update_SPk_test(lime::CurveId::c25519k512); + + lime_update_SPk_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_update_SPk_test(lime::CurveId::c448mlk1024); +#endif #endif } @@ -2223,7 +2278,14 @@ static void lime_update_clean_MK() { lime_update_clean_MK_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_update_clean_MK_test(lime::CurveId::c25519k512); + + lime_update_clean_MK_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_update_clean_MK_test(lime::CurveId::c448mlk1024); +#endif #endif } @@ -2324,7 +2386,14 @@ static void lime_update_republish() { lime_update_republish_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_update_republish_test(lime::CurveId::c25519k512); + + lime_update_republish_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_update_republish_test(lime::CurveId::c448mlk1024); +#endif #endif } /** Scenario @@ -2421,8 +2490,17 @@ static void x3dh_without_OPk() { x3dh_without_OPk_test(lime::CurveId::c448, "lime_x3dh_without_OPk_clean", false); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED x3dh_without_OPk_test(lime::CurveId::c25519k512, "lime_x3dh_without_OPk"); x3dh_without_OPk_test(lime::CurveId::c25519k512, "lime_x3dh_without_OPk_clean", false); + + x3dh_without_OPk_test(lime::CurveId::c25519mlk512, "lime_x3dh_without_OPk"); + x3dh_without_OPk_test(lime::CurveId::c25519mlk512, "lime_x3dh_without_OPk_clean", false); +#endif +#ifdef EC448_ENABLED + x3dh_without_OPk_test(lime::CurveId::c448mlk1024, "lime_x3dh_without_OPk"); + x3dh_without_OPk_test(lime::CurveId::c448mlk1024, "lime_x3dh_without_OPk_clean", false); +#endif #endif } @@ -2572,8 +2650,17 @@ static void x3dh_sending_chain_limit() { x3dh_sending_chain_limit_test(lime::CurveId::c448, "lime_x3dh_sending_chain_limit_clean", false); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED x3dh_sending_chain_limit_test(lime::CurveId::c25519k512, "lime_x3dh_sending_chain_limit"); x3dh_sending_chain_limit_test(lime::CurveId::c25519k512, "lime_x3dh_sending_chain_limit_clean", false); + + x3dh_sending_chain_limit_test(lime::CurveId::c25519mlk512, "lime_x3dh_sending_chain_limit"); + x3dh_sending_chain_limit_test(lime::CurveId::c25519mlk512, "lime_x3dh_sending_chain_limit_clean", false); +#endif +#ifdef EC448_ENABLED + x3dh_sending_chain_limit_test(lime::CurveId::c448mlk1024, "lime_x3dh_sending_chain_limit"); + x3dh_sending_chain_limit_test(lime::CurveId::c448mlk1024, "lime_x3dh_sending_chain_limit_clean", false); +#endif #endif } @@ -2782,8 +2869,17 @@ static void x3dh_multiple_DRsessions(void) { x3dh_multiple_DRsessions_test(lime::CurveId::c448, "lime_x3dh_multiple_DRsessions_clean", false); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED x3dh_multiple_DRsessions_test(lime::CurveId::c25519k512, "lime_x3dh_multiple_DRsessions"); x3dh_multiple_DRsessions_test(lime::CurveId::c25519k512, "lime_x3dh_multiple_DRsessions_clean", false); + + x3dh_multiple_DRsessions_test(lime::CurveId::c25519mlk512, "lime_x3dh_multiple_DRsessions"); + x3dh_multiple_DRsessions_test(lime::CurveId::c25519mlk512, "lime_x3dh_multiple_DRsessions_clean", false); +#endif +#ifdef EC448_ENABLED + x3dh_multiple_DRsessions_test(lime::CurveId::c448mlk1024, "lime_x3dh_multiple_DRsessions"); + x3dh_multiple_DRsessions_test(lime::CurveId::c448mlk1024, "lime_x3dh_multiple_DRsessions_clean", false); +#endif #endif } @@ -2981,8 +3077,17 @@ static void x3dh_multidev_operation_queue(void) { x3dh_multidev_operation_queue_test(lime::CurveId::c448, "lime_x3dh_multidev_operation_queue_clean", false); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED x3dh_multidev_operation_queue_test(lime::CurveId::c25519k512, "lime_x3dh_multidev_operation_queue"); x3dh_multidev_operation_queue_test(lime::CurveId::c25519k512, "lime_x3dh_multidev_operation_queue_clean", false); + + x3dh_multidev_operation_queue_test(lime::CurveId::c25519mlk512, "lime_x3dh_multidev_operation_queue"); + x3dh_multidev_operation_queue_test(lime::CurveId::c25519mlk512, "lime_x3dh_multidev_operation_queue_clean", false); +#endif +#ifdef EC448_ENABLED + x3dh_multidev_operation_queue_test(lime::CurveId::c448mlk1024, "lime_x3dh_multidev_operation_queue"); + x3dh_multidev_operation_queue_test(lime::CurveId::c448mlk1024, "lime_x3dh_multidev_operation_queue_clean", false); +#endif #endif } @@ -3098,8 +3203,17 @@ static void x3dh_operation_queue(void) { x3dh_operation_queue_test(lime::CurveId::c448, "lime_x3dh_operation_queue_clean", false); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED x3dh_operation_queue_test(lime::CurveId::c25519k512, "lime_x3dh_operation_queue"); x3dh_operation_queue_test(lime::CurveId::c25519k512, "lime_x3dh_operation_queue_clean", false); + + x3dh_operation_queue_test(lime::CurveId::c25519mlk512, "lime_x3dh_operation_queue"); + x3dh_operation_queue_test(lime::CurveId::c25519mlk512, "lime_x3dh_operation_queue_clean", false); +#endif +#ifdef EC448_ENABLED + x3dh_operation_queue_test(lime::CurveId::c448mlk1024, "lime_x3dh_operation_queue"); + x3dh_operation_queue_test(lime::CurveId::c448mlk1024, "lime_x3dh_operation_queue_clean", false); +#endif #endif } /* Test Scenario @@ -3214,7 +3328,14 @@ static void lime_identity_theft(void) { lime_identity_theft_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_identity_theft_test(lime::CurveId::c25519k512); + + lime_identity_theft_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_identity_theft_test(lime::CurveId::c448mlk1024); +#endif #endif } /* A simple test with alice having 1 device and bob 2 @@ -3451,9 +3572,20 @@ static void x3dh_basic(void) { x3dh_basic_test(lime::CurveId::c448, "lime_x3dh_basic_AD", true, true); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED x3dh_basic_test(lime::CurveId::c25519k512, "lime_x3dh_basic"); x3dh_basic_test(lime::CurveId::c25519k512, "lime_x3dh_basic_clean", false); x3dh_basic_test(lime::CurveId::c25519k512, "lime_x3dh_basic_AD", true, true); + + x3dh_basic_test(lime::CurveId::c25519mlk512, "lime_x3dh_basic"); + x3dh_basic_test(lime::CurveId::c25519mlk512, "lime_x3dh_basic_clean", false); + x3dh_basic_test(lime::CurveId::c25519mlk512, "lime_x3dh_basic_AD", true, true); +#endif +#ifdef EC448_ENABLED + x3dh_basic_test(lime::CurveId::c448mlk1024, "lime_x3dh_basic"); + x3dh_basic_test(lime::CurveId::c448mlk1024, "lime_x3dh_basic_clean", false); + x3dh_basic_test(lime::CurveId::c448mlk1024, "lime_x3dh_basic_AD", true, true); +#endif #endif } @@ -3558,12 +3690,17 @@ static void x3dh_double_recipient(void) { #ifdef EC25519_ENABLED x3dh_double_recipient_test(lime::CurveId::c25519); #endif -#if 0 #ifdef EC448_ENABLED x3dh_double_recipient_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED x3dh_double_recipient_test(lime::CurveId::c25519k512); + + x3dh_double_recipient_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + x3dh_double_recipient_test(lime::CurveId::c448mlk1024); #endif #endif } @@ -3819,8 +3956,17 @@ static void x3dh_user_not_found(void) { x3dh_user_not_found_test(lime::CurveId::c448, "lime_x3dh_user_not_found_clean", false); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED x3dh_user_not_found_test(lime::CurveId::c25519k512, "lime_x3dh_user_not_found"); x3dh_user_not_found_test(lime::CurveId::c25519k512, "lime_x3dh_user_not_found_clean", false); + + x3dh_user_not_found_test(lime::CurveId::c25519mlk512, "lime_x3dh_user_not_found"); + x3dh_user_not_found_test(lime::CurveId::c25519mlk512, "lime_x3dh_user_not_found_clean", false); +#endif +#ifdef EC448_ENABLED + x3dh_user_not_found_test(lime::CurveId::c448mlk1024, "lime_x3dh_user_not_found"); + x3dh_user_not_found_test(lime::CurveId::c448mlk1024, "lime_x3dh_user_not_found_clean", false); +#endif #endif } @@ -3960,7 +4106,14 @@ static void user_management(void) { user_management_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED user_management_test(lime::CurveId::c25519k512); + + user_management_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + user_management_test(lime::CurveId::c448mlk1024); +#endif #endif } @@ -4127,7 +4280,14 @@ static void user_registration_failure(void) { user_registration_failure_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED user_registration_failure_test(lime::CurveId::c25519k512); + + user_registration_failure_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + user_registration_failure_test(lime::CurveId::c448mlk1024); +#endif #endif } @@ -4523,7 +4683,14 @@ static void lime_multithread(void) { lime_multithread_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_multithread_test(lime::CurveId::c25519k512); + + lime_multithread_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_multithread_test(lime::CurveId::c448mlk1024); +#endif #endif } } @@ -4627,8 +4794,17 @@ static void lime_session_cancel(void) { lime_session_cancel_test(lime::CurveId::c448, "lime_session_cancel_clean", false); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_session_cancel_test(lime::CurveId::c25519k512, "lime_session_cancel"); lime_session_cancel_test(lime::CurveId::c25519k512, "lime_session_cancel_clean", false); + + lime_session_cancel_test(lime::CurveId::c25519mlk512, "lime_session_cancel"); + lime_session_cancel_test(lime::CurveId::c25519mlk512, "lime_session_cancel_clean", false); +#endif +#ifdef EC448_ENABLED + lime_session_cancel_test(lime::CurveId::c448mlk1024, "lime_session_cancel"); + lime_session_cancel_test(lime::CurveId::c448mlk1024, "lime_session_cancel_clean", false); +#endif #endif } @@ -4864,8 +5040,17 @@ static bool lime_kem_asymmetric_ratchet_test(const lime::CurveId curve, const st #endif //HAVE_BCTBXPQ static void lime_kem_asymmetric_ratchet(void) { #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED BC_ASSERT_TRUE(lime_kem_asymmetric_ratchet_test(lime::CurveId::c25519k512, "lime_kem_asymmetric_ratchet")); BC_ASSERT_TRUE(lime_kem_asymmetric_ratchet_test(lime::CurveId::c25519k512, "lime_kem_asymmetric_ratchet_clean")); + + BC_ASSERT_TRUE(lime_kem_asymmetric_ratchet_test(lime::CurveId::c25519mlk512, "lime_kem_asymmetric_ratchet")); + BC_ASSERT_TRUE(lime_kem_asymmetric_ratchet_test(lime::CurveId::c25519mlk512, "lime_kem_asymmetric_ratchet_clean")); +#endif +#ifdef EC448_ENABLED + BC_ASSERT_TRUE(lime_kem_asymmetric_ratchet_test(lime::CurveId::c448mlk1024, "lime_kem_asymmetric_ratchet")); + BC_ASSERT_TRUE(lime_kem_asymmetric_ratchet_test(lime::CurveId::c448mlk1024, "lime_kem_asymmetric_ratchet_clean")); +#endif #endif } diff --git a/tester/lime_massive_group-tester.cpp b/tester/lime_massive_group-tester.cpp index 1eecc38..aaea996 100644 --- a/tester/lime_massive_group-tester.cpp +++ b/tester/lime_massive_group-tester.cpp @@ -173,7 +173,7 @@ static void group_basic_test(const lime::CurveId curve, const std::string &dbBas std::vector<lime::CurveId> algos{curve}; uint64_t start=0,span,startEncrypt=0; if (bench) { // use LOGE for bench report to avoid being flooded by debug logs - LIME_LOGE<<"Running a group of "<<to_string(deviceNumber)<<" on curve"<<((curve==lime::CurveId::c25519)?"25519": ((curve==lime::CurveId::c448)?"448":"25519/Kyber 512"))<<endl; + LIME_LOGE<<"### Running a group of "<<to_string(deviceNumber)<<" on curve "<<lime::CurveId2String(curve); start = bctbx_get_cur_time_ms(); } // loop on all devices and create basics @@ -199,7 +199,7 @@ static void group_basic_test(const lime::CurveId curve, const std::string &dbBas if (bench) { span = bctbx_get_cur_time_ms() - start; - LIME_LOGE<<"Generate and register users in "<<to_string(span)<<" ms ("<<to_string(span/deviceNumber)<<" ms/user)"<<std::endl; + LIME_LOGE<<"Generate and register users in "<<to_string(span)<<" ms ("<<to_string(span/deviceNumber)<<" ms/user)"; start = bctbx_get_cur_time_ms(); } @@ -232,15 +232,15 @@ static void group_basic_test(const lime::CurveId curve, const std::string &dbBas if (bench) { if (i==0) { // first run shall be the longest as we have deviceNumber-1 sessions to establish span = bctbx_get_cur_time_ms() - startEncrypt; - LIME_LOGE<<"first message encrypt(all session to establish) in "<<to_string(span)<<" ms ("<<to_string(float(span)/float(deviceNumber))<<" ms/recipient)"<<std::endl; + LIME_LOGE<<"first message encrypt(all session to establish) in "<<to_string(span)<<" ms ("<<to_string(float(span)/float(deviceNumber))<<" ms/recipient)"; } if (i==1 && senderIndex==0) { // second message in oneTalking mode span = bctbx_get_cur_time_ms() - startEncrypt; - LIME_LOGE<<"second message encrypt(no session to establish) in "<<to_string(span)<<" ms ("<<to_string(float(span)/float(deviceNumber))<<" ms/recipient)"<<std::endl; + LIME_LOGE<<"second message encrypt(no session to establish) in "<<to_string(span)<<" ms ("<<to_string(float(span)/float(deviceNumber))<<" ms/recipient)"; } if (i==deviceNumber-1) { // last run shall be the fastest as we have no session to establish span = bctbx_get_cur_time_ms() - startEncrypt; - LIME_LOGE<<"last message encrypt(no session to establish) in "<<to_string(span)<<" ms ("<<to_string(float(span)/float(deviceNumber))<<" ms/recipient)"<<std::endl; + LIME_LOGE<<"last message encrypt(no session to establish) in "<<to_string(span)<<" ms ("<<to_string(float(span)/float(deviceNumber))<<" ms/recipient)"; } startEncrypt = bctbx_get_cur_time_ms(); } @@ -265,11 +265,11 @@ static void group_basic_test(const lime::CurveId curve, const std::string &dbBas if (bench) { if (i==0) { // first run shall be the longest as we have deviceNumber-1 sessions to establish span = bctbx_get_cur_time_ms() - startEncrypt; - LIME_LOGE<<"first message decrypts in "<<to_string(span)<<" ms ("<<to_string(float(span)/float(oneDecrypt?1:deviceNumber-1))<<" ms/recipient)"<<std::endl; + LIME_LOGE<<"first message decrypts in "<<to_string(span)<<" ms ("<<to_string(float(span)/float(oneDecrypt?1:deviceNumber-1))<<" ms/recipient)"; } if (i==1 && senderIndex==0) { // second message in oneTalking mode span = bctbx_get_cur_time_ms() - startEncrypt; - LIME_LOGE<<"second message decrypts in "<<to_string(span)<<" ms ("<<to_string(float(span)/float(oneDecrypt?1:deviceNumber-1))<<" ms/recipient)"<<std::endl; + LIME_LOGE<<"second message decrypts in "<<to_string(span)<<" ms ("<<to_string(float(span)/float(oneDecrypt?1:deviceNumber-1))<<" ms/recipient)"; } if (i==deviceNumber-1) { // last run shall be the shortest as we have no session to establish span = bctbx_get_cur_time_ms() - startEncrypt; @@ -308,7 +308,14 @@ static void group_one_talking() { group_basic_test(lime::CurveId::c448, "group_one_talking", 10, true); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED group_basic_test(lime::CurveId::c25519k512, "group_one_talking", 10, true); + + group_basic_test(lime::CurveId::c25519mlk512, "group_one_talking", 10, true); +#endif +#ifdef EC448_ENABLED + group_basic_test(lime::CurveId::c448mlk1024, "group_one_talking", 10, true); +#endif #endif } @@ -323,8 +330,7 @@ static void group_one_talking_bench() { // time spent in test is more or less linear to the device number, try to reach the one wich lead to a maximunBenchTime execution span = bctbx_get_cur_time_ms() - start; LIME_LOGE<<"Curve 25519 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; - deviceNumber *= int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2); - deviceNumber += 3; + deviceNumber = int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2 * deviceNumber) + 3; } #endif #ifdef EC448_ENABLED @@ -337,11 +343,11 @@ static void group_one_talking_bench() { // time spent in test is more or less linear to the device number, try to reach the one wich lead to a maximunBenchTime execution span = bctbx_get_cur_time_ms() - start; LIME_LOGE<<"Curve 448 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; - deviceNumber *= int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2); - deviceNumber += 3; + deviceNumber = int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2 * deviceNumber) + 3; } #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED deviceNumber=10; start = bctbx_get_cur_time_ms(); span = 0; @@ -351,10 +357,35 @@ static void group_one_talking_bench() { // time spent in test is more or less linear to the device number, try to reach the one wich lead to a maximunBenchTime execution span = bctbx_get_cur_time_ms() - start; LIME_LOGE<<"Curve 25519/Kyber 512 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; - deviceNumber *= int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2); - deviceNumber += 3; + deviceNumber = int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2 * deviceNumber) + 3; + } + + deviceNumber=10; + start = bctbx_get_cur_time_ms(); + span = 0; + while (span < maximumBenchTime) { + start = bctbx_get_cur_time_ms(); + group_basic_test(lime::CurveId::c25519mlk512, "group_one_talking", deviceNumber, true); + // time spent in test is more or less linear to the device number, try to reach the one wich lead to a maximunBenchTime execution + span = bctbx_get_cur_time_ms() - start; + LIME_LOGE<<"Curve 25519/MLKem 512 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; + deviceNumber = int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2 * deviceNumber) + 3; } #endif +#ifdef EC448_ENABLED + deviceNumber=10; + start = bctbx_get_cur_time_ms(); + span = 0; + while (span < maximumBenchTime) { + start = bctbx_get_cur_time_ms(); + group_basic_test(lime::CurveId::c448mlk1024, "group_one_talking", deviceNumber, true); + // time spent in test is more or less linear to the device number, try to reach the one wich lead to a maximunBenchTime execution + span = bctbx_get_cur_time_ms() - start; + LIME_LOGE<<"Curve 448/MLKem 1024 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; + deviceNumber = int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2 * deviceNumber) + 3; + } +#endif +#endif } static void group_one_talking_one_decrypt_bench() { @@ -368,8 +399,7 @@ static void group_one_talking_one_decrypt_bench() { // time spent in test is more or less linear to the device number, try to reach the one wich lead to a maximunBenchTime execution span = bctbx_get_cur_time_ms() - start; LIME_LOGE<<"Curve 25519 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; - deviceNumber *= int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2); - deviceNumber += 3; + deviceNumber = int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2 * deviceNumber) +3; } #endif #ifdef EC448_ENABLED @@ -382,11 +412,11 @@ static void group_one_talking_one_decrypt_bench() { // time spent in test is more or less linear to the device number, try to reach the one wich lead to a maximunBenchTime execution span = bctbx_get_cur_time_ms() - start; LIME_LOGE<<"Curve 448 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; - deviceNumber *= int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2); - deviceNumber += 3; + deviceNumber = int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2 * deviceNumber) + 3; } #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED deviceNumber=10; start = bctbx_get_cur_time_ms(); span = 0; @@ -396,10 +426,35 @@ static void group_one_talking_one_decrypt_bench() { // time spent in test is more or less linear to the device number, try to reach the one wich lead to a maximunBenchTime execution span = bctbx_get_cur_time_ms() - start; LIME_LOGE<<"Curve 25519/Kyber 512 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; - deviceNumber *= int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2); - deviceNumber += 3; + deviceNumber = int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2 * deviceNumber) + 3; + } + + deviceNumber=10; + start = bctbx_get_cur_time_ms(); + span = 0; + while (span < maximumBenchTime) { + start = bctbx_get_cur_time_ms(); + group_basic_test(lime::CurveId::c25519mlk512, "group_one_talking_one_decrypt", deviceNumber, true, true); + // time spent in test is more or less linear to the device number, try to reach the one wich lead to a maximunBenchTime execution + span = bctbx_get_cur_time_ms() - start; + LIME_LOGE<<"Curve 25519/MLKem 512 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; + deviceNumber = int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2 * deviceNumber) + 3; } #endif +#ifdef EC448_ENABLED + deviceNumber=10; + start = bctbx_get_cur_time_ms(); + span = 0; + while (span < maximumBenchTime) { + start = bctbx_get_cur_time_ms(); + group_basic_test(lime::CurveId::c448mlk1024, "group_one_talking_one_decrypt", deviceNumber, true, true); + // time spent in test is more or less linear to the device number, try to reach the one wich lead to a maximunBenchTime execution + span = bctbx_get_cur_time_ms() - start; + LIME_LOGE<<"Curve 448/MLKem 1024 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; + deviceNumber = int(std::max(float(maximumBenchTime)/float(span), 1.0f) * 1.2 * deviceNumber) + 3; + } +#endif +#endif } static void group_all_talking() { @@ -410,7 +465,14 @@ static void group_all_talking() { group_basic_test(lime::CurveId::c448, "group_all_talking", 10); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED group_basic_test(lime::CurveId::c25519k512, "group_all_talking", 10); + + group_basic_test(lime::CurveId::c25519mlk512, "group_all_talking", 10); +#endif +#ifdef EC448_ENABLED + group_basic_test(lime::CurveId::c448mlk1024, "group_all_talking", 10); +#endif #endif } @@ -425,8 +487,7 @@ static void group_all_talking_bench() { // time spent in test is more or less linear to the square of device number, try to reach the one wich lead to a maximunBenchTime execution span = bctbx_get_cur_time_ms() - start; LIME_LOGE<<"Curve 25519 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; - deviceNumber *= int(std::sqrt(std::max(float(maximumBenchTime)/float(span), 1.0f)) * 1.2); - deviceNumber += 3; + deviceNumber = int(std::sqrt(std::max(float(maximumBenchTime)/float(span), 1.0f)) * 1.2 *deviceNumber) + 3; } #endif #ifdef EC448_ENABLED @@ -439,11 +500,11 @@ static void group_all_talking_bench() { // time spent in test is more or less linear to the square of device number, try to reach the one wich lead to a maximunBenchTime execution span = bctbx_get_cur_time_ms() - start; LIME_LOGE<<"Curve 448 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; - deviceNumber *= int(std::sqrt(std::max(float(maximumBenchTime)/float(span), 1.0f)) * 1.2); - deviceNumber += 3; + deviceNumber = int(std::sqrt(std::max(float(maximumBenchTime)/float(span), 1.0f)) * 1.2 *deviceNumber) + 3; } #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED deviceNumber=10; start = bctbx_get_cur_time_ms(); span = 0; @@ -453,10 +514,35 @@ static void group_all_talking_bench() { // time spent in test is more or less linear to the square of device number, try to reach the one wich lead to a maximunBenchTime execution span = bctbx_get_cur_time_ms() - start; LIME_LOGE<<"Curve 25519/Kyber 512 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; - deviceNumber *= int(std::sqrt(std::max(float(maximumBenchTime)/float(span), 1.0f)) * 1.2); - deviceNumber += 3; + deviceNumber = int(std::sqrt(std::max(float(maximumBenchTime)/float(span), 1.0f)) * 1.2 *deviceNumber) + 3; + } + + deviceNumber=10; + start = bctbx_get_cur_time_ms(); + span = 0; + while (span < maximumBenchTime) { + start = bctbx_get_cur_time_ms(); + group_basic_test(lime::CurveId::c25519mlk512, "group_all_talking", deviceNumber); + // time spent in test is more or less linear to the square of device number, try to reach the one wich lead to a maximunBenchTime execution + span = bctbx_get_cur_time_ms() - start; + LIME_LOGE<<"Curve 25519/MLKem 512 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; + deviceNumber = int(std::sqrt(std::max(float(maximumBenchTime)/float(span), 1.0f)) * 1.2 *deviceNumber) + 3; + } +#endif +#ifdef EC448_ENABLED + deviceNumber=10; + start = bctbx_get_cur_time_ms(); + span = 0; + while (span < maximumBenchTime) { + start = bctbx_get_cur_time_ms(); + group_basic_test(lime::CurveId::c448mlk1024, "group_all_talking", deviceNumber); + // time spent in test is more or less linear to the square of device number, try to reach the one wich lead to a maximunBenchTime execution + span = bctbx_get_cur_time_ms() - start; + LIME_LOGE<<"Curve 448/Kyber 1024 group chat test with "<<to_string(deviceNumber)<<" devices ran in "<<to_string(span)<<" ms"<<std::endl; + deviceNumber = int(std::sqrt(std::max(float(maximumBenchTime)/float(span), 1.0f)) * 1.2 *deviceNumber) + 3; } #endif +#endif } static test_t tests[] = { diff --git a/tester/lime_multialgos-tester.cpp b/tester/lime_multialgos-tester.cpp index 7cfbf87..69f204f 100644 --- a/tester/lime_multialgos-tester.cpp +++ b/tester/lime_multialgos-tester.cpp @@ -135,7 +135,7 @@ static limeX3DHServerPostData X3DHServerPost([](const std::string &url, const st belle_http_provider_send_request(prov,req,l); }); -#if defined(EC25519_ENABLED) && defined(HAVE_BCTBXPQ) +#if defined(HAVE_BCTBXPQ) namespace { /* This function will destroy and recreate managers given in parameter, force deleting all internal cache and start back from what is in local Storage */ void managersClean(std::unique_ptr<LimeManager> &alice, std::unique_ptr<LimeManager> &bob, std::string aliceDb, std::string bobDb) { @@ -233,7 +233,7 @@ static bool multialgos_basic_test(const std::vector<lime::CurveId> aliceAlgos, c } return ret; } -#endif //defined(EC25519_ENABLED) && defined(HAVE_BCTBXPQ) +#endif // defined(HAVE_BCTBXPQ) static void multialgos_basic(void) { #if defined(EC25519_ENABLED) && defined(HAVE_BCTBXPQ) @@ -249,13 +249,40 @@ static void multialgos_basic(void) { BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519k512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519k512, lime::CurveId::c25519}, lime::EncryptionPolicy::cipherMessage,false)); BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519k512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519}, lime::EncryptionPolicy::cipherMessage,false)); BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519k512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519, lime::CurveId::c25519k512}, lime::EncryptionPolicy::cipherMessage,false)); + + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, lime::EncryptionPolicy::DRMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519}, lime::EncryptionPolicy::DRMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519, lime::CurveId::c448mlk1024}, lime::EncryptionPolicy::DRMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, lime::EncryptionPolicy::DRMessage,false)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519}, lime::EncryptionPolicy::DRMessage,false)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519, lime::CurveId::c448mlk1024}, lime::EncryptionPolicy::DRMessage,false)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, lime::EncryptionPolicy::cipherMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519}, lime::EncryptionPolicy::cipherMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519, lime::CurveId::c448mlk1024}, lime::EncryptionPolicy::cipherMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, lime::EncryptionPolicy::cipherMessage,false)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519}, lime::EncryptionPolicy::cipherMessage,false)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c448mlk1024, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519, lime::CurveId::c448mlk1024}, lime::EncryptionPolicy::cipherMessage,false)); +#endif +#if defined(EC448_ENABLED) && defined(HAVE_BCTBXPQ) + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, lime::EncryptionPolicy::DRMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519}, lime::EncryptionPolicy::DRMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519, lime::CurveId::c25519mlk512}, lime::EncryptionPolicy::DRMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, lime::EncryptionPolicy::DRMessage,false)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519}, lime::EncryptionPolicy::DRMessage,false)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519, lime::CurveId::c25519mlk512}, lime::EncryptionPolicy::DRMessage,false)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, lime::EncryptionPolicy::cipherMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519}, lime::EncryptionPolicy::cipherMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519, lime::CurveId::c25519mlk512}, lime::EncryptionPolicy::cipherMessage)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, lime::EncryptionPolicy::cipherMessage,false)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519}, lime::EncryptionPolicy::cipherMessage,false)); + BC_ASSERT_TRUE(multialgos_basic_test(std::vector<lime::CurveId>{lime::CurveId::c25519mlk512, lime::CurveId::c25519}, std::vector<lime::CurveId>{lime::CurveId::c25519, lime::CurveId::c25519mlk512}, lime::EncryptionPolicy::cipherMessage,false)); #endif } -#if defined(EC25519_ENABLED) && defined(HAVE_BCTBXPQ) +#if defined(HAVE_BCTBXPQ) namespace { -const std::vector<lime::CurveId> allAlgos{lime::CurveId::c25519, lime::CurveId::c448, lime::CurveId::c25519k512}; +const std::vector<lime::CurveId> allAlgos{lime::CurveId::c25519, lime::CurveId::c448, lime::CurveId::c25519k512, lime::CurveId::c25519mlk512, lime::CurveId::c448mlk1024}; bool delete_any_user(std::shared_ptr<LimeManager> Manager, std::string &username, const lime::limeCallback &callback, int &counter ) { bool ret = true; // loop on all possible algo and delete the user if it exists @@ -423,7 +450,7 @@ static bool multialgos_four_users_test(const std::vector<std::vector<lime::Curve } return ret; } -#endif // defined(EC25519_ENABLED) && defined(HAVE_BCTBXPQ) +#endif // defined(HAVE_BCTBXPQ) static void multialgos_four_users_basic(void) { #if defined(EC25519_ENABLED) && defined(HAVE_BCTBXPQ) @@ -475,6 +502,20 @@ static void multialgos_four_users_migration(void) { std::vector<std::vector<lime::CurveId>>{{lime::CurveId::c25519}, {lime::CurveId::c25519}, {lime::CurveId::c25519}, {lime::CurveId::c25519}}, lime::EncryptionPolicy::cipherMessage)); #endif +#if defined(EC448_ENABLED) && defined(HAVE_BCTBXPQ) + // Dynamic algo support + BC_ASSERT_TRUE(multialgos_four_users_test( + // alice uses: c448 | c448mlk1024,c448 | c448mlk1024,c448 | c448mlk1024,c448 + // bob uses: c448 | c448 | c448mlk1024,c448 | c448mlk1024,c448 + // claire uses: c448 | c448 | c448 | c448mlk1024,c448 + // dave uses: c448 | c448 | c448 | c448 + std::vector<std::vector<lime::CurveId>>{{lime::CurveId::c448}, {lime::CurveId::c448mlk1024, lime::CurveId::c448}, {lime::CurveId::c448mlk1024, lime::CurveId::c448}, {lime::CurveId::c448mlk1024, lime::CurveId::c448}}, + std::vector<std::vector<lime::CurveId>>{{lime::CurveId::c448}, {lime::CurveId::c448}, {lime::CurveId::c448mlk1024, lime::CurveId::c448}, {lime::CurveId::c448mlk1024, lime::CurveId::c448}}, + std::vector<std::vector<lime::CurveId>>{{lime::CurveId::c448}, {lime::CurveId::c448}, {lime::CurveId::c448}, {lime::CurveId::c448mlk1024, lime::CurveId::c448}}, + std::vector<std::vector<lime::CurveId>>{{lime::CurveId::c448}, {lime::CurveId::c448}, {lime::CurveId::c448}, {lime::CurveId::c448}}, + lime::EncryptionPolicy::cipherMessage)); +#endif + } /* diff --git a/tester/lime_multidomains-tester.cpp b/tester/lime_multidomains-tester.cpp index acb623a..a64fecf 100644 --- a/tester/lime_multidomains-tester.cpp +++ b/tester/lime_multidomains-tester.cpp @@ -211,7 +211,14 @@ static void lime_multidomains_simple() { lime_multidomains_simple_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_multidomains_simple_test(lime::CurveId::c25519k512); + + lime_multidomains_simple_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_multidomains_simple_test(lime::CurveId::c448mlk1024); +#endif #endif } @@ -327,7 +334,14 @@ static void lime_multidomains_several_foreign() { lime_multidomains_several_foreign_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_multidomains_several_foreign_test(lime::CurveId::c25519k512); + + lime_multidomains_several_foreign_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_multidomains_several_foreign_test(lime::CurveId::c448mlk1024); +#endif #endif } // Scenario: @@ -482,7 +496,14 @@ static void lime_multidomains_several_users_foreign() { lime_multidomains_several_users_foreign_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_multidomains_several_users_foreign_test(lime::CurveId::c25519k512); + + lime_multidomains_several_users_foreign_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_multidomains_several_users_foreign_test(lime::CurveId::c448mlk1024); +#endif #endif } diff --git a/tester/lime_server-tester.cpp b/tester/lime_server-tester.cpp index ebc9efa..e10c11b 100644 --- a/tester/lime_server-tester.cpp +++ b/tester/lime_server-tester.cpp @@ -218,7 +218,14 @@ static void lime_server_resource_limit_reached() { lime_server_resource_limit_reached_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_server_resource_limit_reached_test(lime::CurveId::c25519k512); + + lime_server_resource_limit_reached_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_server_resource_limit_reached_test(lime::CurveId::c448mlk1024); +#endif #endif } @@ -348,10 +355,17 @@ static void lime_server_bundle_request_limit_reached() { lime_server_bundle_request_limit_reached_test(lime::CurveId::c25519, "lime_server_bundle_request_limit_reached_keep", lime_tester::test_x3dh_default_server); #endif #ifdef EC448_ENABLED - //lime_server_bundle_request_limit_reached_test(lime::CurveId::c448, "lime_server_bundle_request_limit_reached_keep", lime_tester::test_x3dh_default_server); + lime_server_bundle_request_limit_reached_test(lime::CurveId::c448, "lime_server_bundle_request_limit_reached_keep", lime_tester::test_x3dh_default_server); #endif #ifdef HAVE_BCTBXPQ - //lime_server_bundle_request_limit_reached_test(lime::CurveId::c25519k512, "lime_server_bundle_request_limit_reached_keep", lime_tester::test_x3dh_default_server); +#ifdef EC25519_ENABLED + lime_server_bundle_request_limit_reached_test(lime::CurveId::c25519k512, "lime_server_bundle_request_limit_reached_keep", lime_tester::test_x3dh_default_server); + + lime_server_bundle_request_limit_reached_test(lime::CurveId::c25519mlk512, "lime_server_bundle_request_limit_reached_keep", lime_tester::test_x3dh_default_server); +#endif +#ifdef EC448_ENABLED + lime_server_bundle_request_limit_reached_test(lime::CurveId::c448mlk1024, "lime_server_bundle_request_limit_reached_keep", lime_tester::test_x3dh_default_server); +#endif #endif } @@ -363,7 +377,14 @@ static void lime_server_bundle_request_limit_reached_stop_serving() { lime_server_bundle_request_limit_reached_test(lime::CurveId::c448, "lime_server_bundle_request_limit_reached_stop", lime_tester::test_x3dh_stop_on_request_limit_server, false); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_server_bundle_request_limit_reached_test(lime::CurveId::c25519k512, "lime_server_bundle_request_limit_reached_stop", lime_tester::test_x3dh_stop_on_request_limit_server, false); + + lime_server_bundle_request_limit_reached_test(lime::CurveId::c25519mlk512, "lime_server_bundle_request_limit_reached_stop", lime_tester::test_x3dh_stop_on_request_limit_server, false); +#endif +#ifdef EC448_ENABLED + lime_server_bundle_request_limit_reached_test(lime::CurveId::c448mlk1024, "lime_server_bundle_request_limit_reached_stop", lime_tester::test_x3dh_stop_on_request_limit_server, false); +#endif #endif } @@ -559,7 +580,14 @@ static void lime_server_bundle_request_limit_reached_multiple_users() { lime_server_bundle_request_limit_reached_multiple_users_test(lime::CurveId::c448); #endif #ifdef HAVE_BCTBXPQ +#ifdef EC25519_ENABLED lime_server_bundle_request_limit_reached_multiple_users_test(lime::CurveId::c25519k512); + + lime_server_bundle_request_limit_reached_multiple_users_test(lime::CurveId::c25519mlk512); +#endif +#ifdef EC448_ENABLED + lime_server_bundle_request_limit_reached_multiple_users_test(lime::CurveId::c448mlk1024); +#endif #endif } -- GitLab From 2a7875c8f205e576f513f256f7d448588dca31b9 Mon Sep 17 00:00:00 2001 From: johan pascal <johan.pascal@belledonne-communications.com> Date: Mon, 13 Jan 2025 10:24:09 +0100 Subject: [PATCH 3/5] Update changelog --- CHANGELOG.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc4721b..f27b4ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [5.3.0] - XXXX-XX-XX +## [5.4.0] - 2024-01-14 +### Added +- Support for KEM algorithms in X3DH and DR. Add support for mix usage: + - X25519+Kyber512 + - X25519+MLKem512 + - X448+MLKem1024 +- Support multiple base algorithm for one user +### Changed +- Devices are identified by GRUU+base Algo + +## [5.3.0] - 2023-11-23 ### Changed - Lime manager keeps an open connexion to the db - Update timer is managed internally: keep track of last successful update for each local user -- GitLab From 85fb17ecf17ba68e7bf744a4656314453e429015 Mon Sep 17 00:00:00 2001 From: johan pascal <johan.pascal@belledonne-communications.com> Date: Mon, 13 Jan 2025 23:55:53 +0100 Subject: [PATCH 4/5] Fix nodejs test server --- tester/server/nodejs/README.md | 28 +- tester/server/nodejs/curveIds.js | 10 + tester/server/nodejs/localServerStart.sh | 8 +- tester/server/nodejs/multiserver.cfg | 11 + tester/server/nodejs/x3dh.js | 366 +++++++++++------------ 5 files changed, 219 insertions(+), 204 deletions(-) create mode 100644 tester/server/nodejs/curveIds.js create mode 100644 tester/server/nodejs/multiserver.cfg diff --git a/tester/server/nodejs/README.md b/tester/server/nodejs/README.md index 50153bc..49a5bf6 100644 --- a/tester/server/nodejs/README.md +++ b/tester/server/nodejs/README.md @@ -30,30 +30,38 @@ node x3dh.js -d <path> [options] Options: --help Show help [boolean] --version Show version number [boolean] - --database, -d path to database file [string] [required] + --setting, -s path to configuration file + [string] [default:multiserver.cfg] --port, -p port to listen [number] [default: 25519] --certificate, -c path to server certificate [string] [default: "x3dh-cert.pem"] --key, -k path to server private key [string] [default: "x3dh-key.pem"] - --ellipticCurve, -e set which Elliptic Curve users of this server must use, - option used once at database creation, it is then ignored - [string] [choices: "c25519", "c448"] [default: "c25519"] --resource_dir, -r set directory path to used as base to find database and key files [string] [default: "./"] --lifetime, -l lifetime of a user in seconds, 0 is forever. [number] [default: 300] +Setting +------- +Configuration file must export an associative array + - CurveId => Db Path +For all the curve Id enabled on the server +Default is to enable all the available ones: + - c25519 + - c448 + - c25519/kyber512 + - c25519/mlkem512 + - c488/mlkem1024 + Script ------ -Server is managing one type of keys(Curve 25519 or Curve 448 based). To run automated tests if you build liblime with all algorithms enabled you must -run three servers, on ports 25519, 25520 and 25526 +support all the available base algorithm. +Note: multidomains and lime server test suites are not supported by the default configuration A convenient launching script is provided : localServerStart.sh It does: - killall nodejs instance running(beware if you use it no shared server) -- wipe out c25519.sqlite3, c448.sqlite3 and c25519k512.sqlite3 -- start server using c22519.sqlite3 db listening on port 25519 using curve25519 -- start server using c448.sqlite3 db listening on port 25520 using curve448 -- start server using c25519k512.sqlite3 db listening on port 25526 using curve25519k512 +- wipe out c25519.sqlite3, c448.sqlite3, c25519k512.sqlite3, c25519mlk512.sqlite and c448mlk1024.sqlite +- start a server supporting all the available base algorithms using the previous files as DB diff --git a/tester/server/nodejs/curveIds.js b/tester/server/nodejs/curveIds.js new file mode 100644 index 0000000..63fbaaf --- /dev/null +++ b/tester/server/nodejs/curveIds.js @@ -0,0 +1,10 @@ +// WARNING: value shall be in sync with defines in client code: Curve25519 = 1, Curve448 = 2 ecc.. +module.exports = { + UNSET : 0, + CURVE25519 : 1, + CURVE448 : 2, + CURVE25519K512: 3, + CURVE25519MLK512: 4, + CURVE448MLK1024: 5 +}; + diff --git a/tester/server/nodejs/localServerStart.sh b/tester/server/nodejs/localServerStart.sh index 33eebb0..8929a0d 100755 --- a/tester/server/nodejs/localServerStart.sh +++ b/tester/server/nodejs/localServerStart.sh @@ -1 +1,7 @@ -killall node; rm c25519.sqlite3; rm c448.sqlite3; rm c25519k512.sqlite3; node x3dh.js -d c25519.sqlite3 & node x3dh.js -d c448.sqlite3 -p 25520 -e c448 & node x3dh.js -d c25519k512.sqlite3 -p 25526 -e c25519k512 +killall node; +rm c25519.sqlite3; +rm c448.sqlite3; +rm c25519k512.sqlite3; +rm c25519mlk512.sqlite3; +rm c448mlk1024.sqlite3; +node x3dh.js diff --git a/tester/server/nodejs/multiserver.cfg b/tester/server/nodejs/multiserver.cfg new file mode 100644 index 0000000..115a39c --- /dev/null +++ b/tester/server/nodejs/multiserver.cfg @@ -0,0 +1,11 @@ +// retrieve the list of available curveIds +const enum_id = require('./curveIds.js'); + +// Enable some of them and connect them to a DB +module.exports = { + [enum_id.CURVE25519]: "c25519.sqlite3", + [enum_id.CURVE448]: "c448.sqlite3", + [enum_id.CURVE25519K512]: "c25519k512.sqlite3", + [enum_id.CURVE25519MLK512]: "c25519mlk512.sqlite3", + [enum_id.CURVE448MLK1024]: "c448mlk1024.sqlite3", +}; diff --git a/tester/server/nodejs/x3dh.js b/tester/server/nodejs/x3dh.js index 07a3704..b0ad6e9 100644 --- a/tester/server/nodejs/x3dh.js +++ b/tester/server/nodejs/x3dh.js @@ -1,7 +1,7 @@ /* x3dh node server author Johan Pascal - copyright Copyright (C) 2017 Belledonne Communications SARL + copyright Copyright (C) 2017-2025 Belledonne Communications SARL This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,11 +23,11 @@ // path to server certificate default to ./x3dh-cert.pem // path to server key default to ./x3dh-key.pem const yargs = require('yargs') - .option('database', { - alias : 'd', - describe: 'path to database file', - demandOption: true, - type: 'string' + .option('setting', { + alias : 's', + describe: 'path to the config file', + type: 'string', + default: 'multiserver.cfg' }) .option('port', { alias : 'p', @@ -47,13 +47,6 @@ const yargs = require('yargs') type: 'string', default : 'x3dh-key.pem' }) - .option('ellipticCurve', { - alias : 'e', - describe: 'set which base crypto algorithm users of this server must use, option used once at database creation, it is then ignored', - type : 'string', - choices : ['c25519', 'c448', 'c25519k512'], - default : 'c25519' - }) .option('resource_dir', { alias : 'r', describe : 'set directory path to used as base to find database and key files', @@ -79,13 +72,11 @@ const options = { cert: fs.readFileSync(yargs.resource_dir+"/"+yargs.certificate) }; -// define the curve Id used on this server, default is curve25519, it will be either load from DB or got from args if we are creation the DB. -// WARNING: value shall be in sync with defines in client code: Curve25519 = 1, Curve448 = 2 */ -const enum_curveId = { - CURVE25519 : 1, - CURVE448 : 2, - CURVE25519K512: 3 -}; +// retrieve the list of available curve Ids as an enum +const enum_curveId = require('./curveIds.js'); + +// get the enabled curves from configuration file: curveId->db path +var dbs = require((yargs.resource_dir+"/"+yargs.setting)); // Resource abuse protection // Setting to 0 disable the function @@ -93,10 +84,6 @@ const enum_curveId = { // Do not set this value too low, it shall not be lower than the server_low_limit+batch_size used by client - default is 100+25 const lime_max_opk_per_device = 200; - - -var curveId = enum_curveId.CURVE25519; - const X3DH_protocolVersion = 0x01; const X3DH_headerSize = 3; @@ -134,16 +121,25 @@ const enum_keyBundleFlag = { noBundle : 0x02 }; -const keySizes = { // 1 is for enum_curveId.CURVE25519, 2 is for enum_curveId.CURVE448, 3 is for enum_curveId.CURVE25519K512 +const keySizes = { // 1 is for enum_curveId.CURVE25519 + // 2 is for enum_curveId.CURVE448 + // 3 is for enum_curveId.CURVE25519K512 + // 4 is for enum_curveId.CURVE25519MLK512 + // 5 is for enum_curveId.CURVE448MLK1024 1 : {X_pub : 32, ED_pub : 32, Sig : 64, OPk : 32, SPk : 96, Ik : 32}, 2 : {X_pub : 56, ED_pub : 57, Sig : 114, OPk : 56, SPk : 170, Ik : 57}, - 3 : {X_pub : 832, ED_pub : 32, Sig : 64, OPk : 896, SPk : 896, Ik : 32} + 3 : {X_pub : 832, ED_pub : 32, Sig : 64, OPk : 832, SPk : 896, Ik : 32}, + 4 : {X_pub : 832, ED_pub : 32, Sig : 64, OPk : 832, SPk : 896, Ik : 32}, + 5 : {X_pub : 1624, ED_pub : 57, Sig : 114, OPk : 1624, SPk : 1738, Ik : 57} }; -// open DataBase -var db = new sqlite3.Database(yargs.resource_dir+yargs.database); + +// open DataBases +function openDb(curveId, dbPath) { +console.log(`Open DB : ${dbPath} on curve ${curveId}`); +let db = new sqlite3.Database(yargs.resource_dir+dbPath); db.run("PRAGMA foreign_keys = ON;"); // enable foreign keys -db.run("PRAGMA synchronous = OFF;"); // WARNING: huge performance boost be DON'T DO THAT ON A REAL SERVER. +//db.run("PRAGMA synchronous = OFF;"); // WARNING: huge performance boost be DON'T DO THAT ON A REAL SERVER. //db.on('trace', function(query) {console.log(query);}); //db.on('profile', function(query,time) {console.log("Profile Sqlite "); console.log(query); console.log(time);}); @@ -151,18 +147,7 @@ db.run("PRAGMA synchronous = OFF;"); // WARNING: huge performance boost be DON'T // Check the user version, do we need to do something on this DB? db.get("PRAGMA user_version;", function(err, row) { if (row.user_version < 1) { // current user version is 1 - switch (yargs.ellipticCurve) { - case 'c25519': - curveId=enum_curveId.CURVE25519; - break; - case 'c25519k512': - curveId=enum_curveId.CURVE25519K512; - break; - case 'c448': - curveId=enum_curveId.CURVE448; - break; - } - console.log("Create Database "+yargs.database+" using curve "+yargs.ellipticCurve+" (id "+curveId+")"); + console.log("Create Database "+dbPath+" using curve id "+curveId); db.run( /* Users table: * - id as primary key (internal use) @@ -188,33 +173,25 @@ db.get("PRAGMA user_version;", function(err, row) { } else { // load config table and display it db.get("SELECT CurveId FROM Config", function (err, row) { - switch (row.CurveId) { - case enum_curveId.CURVE25519: - console.log("Open DB "+yargs.database+" using curve c25519"); - curveId = enum_curveId.CURVE25519; - break; - case enum_curveId.CURVE448: - console.log("Open DB "+yargs.database+" using curve c448"); - curveId = enum_curveId.CURVE448; - break; - case enum_curveId.CURVE25519K512: - console.log("Open DB "+yargs.database+" using algo c25519k512"); - curveId = enum_curveId.CURVE25519K512; - break; - default: - console.log("Open DB "+yargs.database+" but unable to pick or unknow curve in config table"+row.CurveId); - process.exit(1); - break; + if (row.CurveId != curveId) { + console.log("Open DB "+dbPath+" expect curveId to be "+curveId+" but found "+row.CurveId); + process.exit(1); } }); } }); +return db; +} +// open the databases according to setting: turns dbs from curveId->dbPath to curveId->db Object +for (const [curveId, dbPath] of Object.entries(dbs)) { + dbs[curveId] = openDb(curveId, dbPath); +} -function deleteUser(userId) { +function deleteUser(curveId, userId) { lock.writeLock(function (release) { - db.run("DELETE FROM Users WHERE UserId = ?;", [userId], function(errDelete){ + dbs[curveId].run("DELETE FROM Users WHERE UserId = ?;", [userId], function(errDelete){ release(); - console.log("Timeout for user "+userId); + console.log("Timeout for user "+userId+" on curveId "+curveId); }) }) } @@ -226,10 +203,10 @@ function arrayEquals(array1, array2) { // start https server console.log("X3DH server on, listening port "+yargs.port); https.createServer(options, (req, res) => { - function returnError(code, errorMessage) { + function returnError(curveId, code, errorMessage) { console.log("return an error message code "+code+" : "+errorMessage); - var errorBuffer = Buffer.from([X3DH_protocolVersion, enum_messageTypes.error, curveId, code]); // build the X3DH response header, append the error code - var errorString = Buffer.from(errorMessage); // encode the errorMessage in UTF8 in a buffer + let errorBuffer = Buffer.from([X3DH_protocolVersion, enum_messageTypes.error, curveId, code]); // build the X3DH response header, append the error code + let errorString = Buffer.from(errorMessage); // encode the errorMessage in UTF8 in a buffer errorBuffer = Buffer.concat([errorBuffer, errorString]); res.writeHead(200, {'Content-type' : 'x3dh/octet-stream'}); console.log("returned message ("+errorBuffer.length+" bytes):"+errorBuffer.toString('hex')); @@ -246,46 +223,48 @@ https.createServer(options, (req, res) => { // is this someone trying to post something if (req.method=='POST') { - var body = Buffer.allocUnsafe(0); + let userId = null; + let body = Buffer.allocUnsafe(0); req.on('data', function(data) { body = Buffer.concat([body, data]); }); req.on('end', function() { // check http header if (req.headers['content-type'] != 'x3dh/octet-stream') { - returnError(enum_errorCodes.bad_content_type, "Accept x3dh/octet-stream content type only, not "+req.headers['content-type']); + returnError(enum_CurveId.UNSET, enum_errorCodes.bad_content_type, "Accept x3dh/octet-stream content type only, not "+req.headers['content-type']); return; } if (!("x-lime-user-identity" in req.headers)) { // user id (GRUU) in HTTP custom header if (!("from" in req.headers)) { // legacy : user id in HTTP from - returnError(enum_errorCodes.missing_senderId, "X-Lime-user-identity or From field must be present in http packet header"); + returnError(enum_CurveId.UNSET, enum_errorCodes.missing_senderId, "X-Lime-user-identity or From field must be present in http packet header"); return; } else { - var userId = req.headers['from']; + userId = req.headers['from']; } } else { - var userId = req.headers['x-lime-user-identity']; + userId = req.headers['x-lime-user-identity']; } // do we have at least a header to parse? if (body.length<X3DH_headerSize) { - returnError(enum_errorCodes.bad_size, "Packet is not even holding a header. Size "+body.length); + returnError(enum_CurveId.UNSET, enum_errorCodes.bad_size, "Packet is not even holding a header. Size "+body.length); return; } // Check X3DH header // parse message header - var protocolVersion = body.readUInt8(0); - var messageType = body.readUInt8(1); - var message_curveId = body.readUInt8(2); + let protocolVersion = body.readUInt8(0); + let messageType = body.readUInt8(1); + let currentCurveId = body.readUInt8(2); if (protocolVersion != X3DH_protocolVersion) { - returnError(enum_errorCodes.bad_x3dh_protocol_version, "Server running X3DH procotol version "+X3DH_protocolVersion+". Can't process packet with version "+protocolVersion); + returnError(currentCurveId, enum_errorCodes.bad_x3dh_protocol_version, "Server running X3DH procotol version "+X3DH_protocolVersion+". Can't process packet with version "+protocolVersion); return; } - if (message_curveId != curveId) { - returnError(enum_errorCodes.bad_curve, "Server running X3DH procotol using curve (id "+curveId+"). Can't serve client using curveId "+message_curveId); + // is this one supported in the config? + if (!dbs.hasOwnProperty(currentCurveId)) { + returnError(currentCurveId, enum_errorCodes.bad_curve, "Server running X3DH procotol can't serve client using curveId "+currentCurveId); return; } @@ -293,9 +272,10 @@ https.createServer(options, (req, res) => { //let db = new sqlite3.Database(yargs.resource_dir+yargs.database); //db.run("PRAGMA foreign_keys = ON;"); // enable foreign keys - var returnHeader = Buffer.from([protocolVersion, messageType, message_curveId]); // acknowledge message by sending an empty message with same header (modified in case of getPeerBundle request) + let returnHeader = Buffer.from([protocolVersion, messageType, currentCurveId]); // acknowledge message by sending an empty message with same header (modified in case of getPeerBundle request) switch (messageType) { /* Deprecated Register User Identity Key : Identity Key <EDDSA Public key size >*/ + /* case enum_messageTypes.deprecated_registerUser: console.log("Got a deprecated registerUser Message from "+userId); var x3dh_expectedSize = keySizes[curveId]['ED_pub']; @@ -328,54 +308,54 @@ https.createServer(options, (req, res) => { }); }); break; - +*/ /* Register User Identity Key : * Identity Key <EDDSA Public key size > | * Signed Pre Key <ECDH public key size> | SPk Signature <Signature length> | SPk id <uint32_t big endian: 4 bytes> * OPk number < uint16_t big endian: 2 bytes> | (OPk <ECDH public key size> | OPk id <uint32_t big endian: 4 bytes> ){OPk number} */ - case enum_messageTypes.registerUser: + case enum_messageTypes.registerUser: { console.log("Got a registerUser Message from "+userId); // check we have at least Ik, SPk, SPk_sig, SPk_Id and OPk_count - var x3dh_expectedSize = keySizes[curveId]['Ik'] // Ik - + keySizes[curveId]['SPk'] + 4 //SPk, SPk_Sig, SPk_id + let x3dh_expectedSize = keySizes[currentCurveId]['Ik'] // Ik + + keySizes[currentCurveId]['SPk'] + 4 //SPk, SPk_Sig, SPk_id +2; // OPk count if (body.length<X3DH_headerSize + x3dh_expectedSize) { - returnError(enum_errorCodes.bad_size, "Register User packet is expected to be at least(without OPk) "+(X3DH_headerSize+x3dh_expectedSize)+" bytes, but we got "+body.length+" bytes"); + returnError(currentCurveId, enum_errorCodes.bad_size, "Register User packet is expected to be at least(without OPk) "+(X3DH_headerSize+x3dh_expectedSize)+" bytes, but we got "+body.length+" bytes"); return; } // Now get the OPk count - var bufferIndex = X3DH_headerSize; - var OPk_number = body.readUInt16BE(bufferIndex+x3dh_expectedSize-2); + let bufferIndex = X3DH_headerSize; + let OPk_number = body.readUInt16BE(bufferIndex+x3dh_expectedSize-2); if ((lime_max_opk_per_device > 0) && (OPk_number > lime_max_opk_per_device)) { // too much OPk, reject registration - returnError(enum_errorCodes.resource_limit_reached, userId+" is trying to register itself with "+OPk_number+" OPks but server has a limit of "+lime_max_opk_per_device); + returnError(currentCurveId, enum_errorCodes.resource_limit_reached, userId+" is trying to register itself with "+OPk_number+" OPks but server has a limit of "+lime_max_opk_per_device); return; } // And check again the size with OPks - x3dh_expectedSize += OPk_number*(keySizes[curveId]['OPk'] + 4); + x3dh_expectedSize += OPk_number*(keySizes[currentCurveId]['OPk'] + 4); if (body.length<X3DH_headerSize + x3dh_expectedSize) { - returnError(enum_errorCodes.bad_size, "Register User packet is expected to be (with "+OPk_number+" OPks) "+(X3DH_headerSize+x3dh_expectedSize)+" bytes, but we got "+body.length+" bytes"); + returnError(currentCurveId, enum_errorCodes.bad_size, "Register User packet is expected to be (with "+OPk_number+" OPks) "+(X3DH_headerSize+x3dh_expectedSize)+" bytes, but we got "+body.length+" bytes"); return; } // Read Ik - var Ik = body.slice(bufferIndex, bufferIndex + keySizes[curveId]['Ik']); - bufferIndex += keySizes[curveId]['Ik']; + let Ik = body.slice(bufferIndex, bufferIndex + keySizes[currentCurveId]['Ik']); + bufferIndex += keySizes[currentCurveId]['Ik']; // SPk - var SPk = body.slice(bufferIndex, bufferIndex + keySizes[curveId]['X_pub']); - bufferIndex += keySizes[curveId]['X_pub']; + let SPk = body.slice(bufferIndex, bufferIndex + keySizes[currentCurveId]['X_pub']); + bufferIndex += keySizes[currentCurveId]['X_pub']; // SPk Sig - var Sig = body.slice(bufferIndex, bufferIndex + keySizes[curveId]['Sig']); - bufferIndex += keySizes[curveId]['Sig']; + let Sig = body.slice(bufferIndex, bufferIndex + keySizes[currentCurveId]['Sig']); + bufferIndex += keySizes[currentCurveId]['Sig']; // SPk Id - var SPk_id = body.readUInt32BE(bufferIndex); // SPk id is a 32 bits unsigned integer in Big endian + let SPk_id = body.readUInt32BE(bufferIndex); // SPk id is a 32 bits unsigned integer in Big endian bufferIndex += 6; // 4 from SPk_id and 2 from OPk count. // all OPks - var OPks_param = []; + let OPks_param = []; for (let i = 0; i < OPk_number; i++) { - var OPk = body.slice(bufferIndex, bufferIndex + keySizes[curveId]['OPk']); - bufferIndex += keySizes[curveId]['OPk']; - var OPk_id = body.readUInt32BE(bufferIndex); // SPk id is a 32 bits unsigned integer in Big endian + let OPk = body.slice(bufferIndex, bufferIndex + keySizes[currentCurveId]['OPk']); + bufferIndex += keySizes[currentCurveId]['OPk']; + let OPk_id = body.readUInt32BE(bufferIndex); // SPk id is a 32 bits unsigned integer in Big endian bufferIndex += 4; OPks_param.push([OPk, OPk_id]); } @@ -384,7 +364,7 @@ https.createServer(options, (req, res) => { lock.writeLock(function (release) { // check it is not already present in DB - db.get("SELECT Uid,Ik,SPk,SPk_sig,SPk_id FROM Users WHERE UserId = ?;", userId , function (err, row) { + dbs[currentCurveId].get("SELECT Uid,Ik,SPk,SPk_sig,SPk_id FROM Users WHERE UserId = ?;", userId , function (err, row) { if (row != undefined) { // usedId is already present in base // Check that Ik, SPk, SPk_sig match the content of the message if (arrayEquals(row['Ik'], Ik) && arrayEquals(row['SPk'], SPk) && arrayEquals(row['SPk_sig'], Sig) && SPk_id === row['SPk_id']) { @@ -393,18 +373,18 @@ https.createServer(options, (req, res) => { release(); } else { release(); - returnError(enum_errorCodes.user_already_in, "Can't insert user "+userId+" - is already present in base and we try to insert a new one with differents Keys"); + returnError(currentCurveId, enum_errorCodes.user_already_in, "Can't insert user "+userId+" - is already present in base and we try to insert a new one with differents Keys"); } } else { - db.run("begin transaction"); - db.run("INSERT INTO Users(UserId,Ik,SPk,SPk_sig,SPk_id) VALUES(?,?,?,?,?);", [userId, Ik, SPk, Sig, SPk_id], function(errInsert){ + dbs[currentCurveId].run("begin transaction"); + dbs[currentCurveId].run("INSERT INTO Users(UserId,Ik,SPk,SPk_sig,SPk_id) VALUES(?,?,?,?,?);", [userId, Ik, SPk, Sig, SPk_id], function(errInsert){ if (errInsert == null) { // Now bulk insert the OPks - var Uid = this.lastID; - var stmt_ran = 0; - var stmt_success = 0; - var stmt_err_message = ''; - var stmt = db.prepare("INSERT INTO OPk(Uid, OPk, OPk_id) VALUES(?,?,?);") + let Uid = this.lastID; + let stmt_ran = 0; + let stmt_success = 0; + let stmt_err_message = ''; + let stmt = dbs[currentCurveId].prepare("INSERT INTO OPk(Uid, OPk, OPk_id) VALUES(?,?,?);") for (let i=0; i<OPks_param.length; i++) { param = OPks_param[i]; stmt.run([Uid, param[0], param[1]], function(stmt_err, stmt_res){ // callback is called for each insertion, so we shall count errors and success @@ -416,15 +396,15 @@ https.createServer(options, (req, res) => { } if (stmt_ran == OPk_number) { // and react only when we reach correct count if (stmt_ran != stmt_success) { - db.run("rollback") + dbs[currentCurveId].run("rollback") release(); - returnError(enum_errorCodes.db_error, "Error while trying to insert OPk for user "+userId+". Backend says :"+stmt_err); + returnError(currentCurveId, enum_errorCodes.db_error, "Error while trying to insert OPk for user "+userId+". Backend says :"+stmt_err); } else { - db.run("commit") + dbs[currentCurveId].run("commit") release(); if (yargs.lifetime!=0) { console.log("User inserted will be deleted in "+yargs.lifetime*1000); - setTimeout(deleteUser, yargs.lifetime*1000, userId); + setTimeout(deleteUser, yargs.lifetime*1000, currentCurveId, userId); } returnOk(returnHeader); } @@ -434,82 +414,82 @@ https.createServer(options, (req, res) => { } else { release(); console.log("INSERT failed err is "); console.log(errInsert); - returnError(enum_errorCodes.db_error, "Error while trying to insert user "+userId); + returnError(currentCurveId, enum_errorCodes.db_error, "Error while trying to insert user "+userId); } }); } }); }); - break; + }break; /* Delete user: message is empty(or at least shall be, anyway, just ignore anything present in the messange and just delete the user given in From header */ - case enum_messageTypes.deleteUser: + case enum_messageTypes.deleteUser:{ console.log("Got a deleteUser Message from "+userId); lock.writeLock(function (release) { - db.run("DELETE FROM Users WHERE UserId = ?;", [userId], function(errDelete){ + dbs[currentCurveId].run("DELETE FROM Users WHERE UserId = ?;", [userId], function(errDelete){ release(); if (errDelete == null) { returnOk(returnHeader); } else { console.log("DELETE failed err is "); console.log(errInsert); - returnError(enum_errorCodes.db_error, "Error while trying to delete user "+userId); + returnError(currentCurveId, enum_errorCodes.db_error, "Error while trying to delete user "+userId); } }); }); - break; + }break; /* Post Signed Pre Key: Signed Pre Key <ECDH public key size> | SPk Signature <Signature length> | SPk id <uint32_t big endian: 4 bytes> */ - case enum_messageTypes.postSPk: - var x3dh_expectedSize = keySizes[curveId]['SPk'] + 4; + case enum_messageTypes.postSPk:{ + let x3dh_expectedSize = keySizes[currentCurveId]['SPk'] + 4; console.log("Got a postSPk Message from "+userId); if (body.length<X3DH_headerSize + x3dh_expectedSize) { - returnError(enum_errorCodes.bad_size, "post SPK packet is expexted to be "+(X3DH_headerSize+x3dh_expectedSize)+" bytes, but we got "+body.length+" bytes"); + returnError(currentCurveId, enum_errorCodes.bad_size, "post SPK packet is expexted to be "+(X3DH_headerSize+x3dh_expectedSize)+" bytes, but we got "+body.length+" bytes"); return; } // parse message - var bufferIndex = X3DH_headerSize; - var SPk = body.slice(bufferIndex, bufferIndex + keySizes[curveId]['X_pub']); - bufferIndex += keySizes[curveId]['X_pub']; - var Sig = body.slice(bufferIndex, bufferIndex + keySizes[curveId]['Sig']); - bufferIndex += keySizes[curveId]['Sig']; - var SPk_id = body.readUInt32BE(bufferIndex); // SPk id is a 32 bits unsigned integer in Big endian + let bufferIndex = X3DH_headerSize; + let SPk = body.slice(bufferIndex, bufferIndex + keySizes[currentCurveId]['X_pub']); + bufferIndex += keySizes[currentCurveId]['X_pub']; + let Sig = body.slice(bufferIndex, bufferIndex + keySizes[currentCurveId]['Sig']); + bufferIndex += keySizes[currentCurveId]['Sig']; + let SPk_id = body.readUInt32BE(bufferIndex); // SPk id is a 32 bits unsigned integer in Big endian // check we have a matching user in DB lock.writeLock(function (release) { - db.get("SELECT Uid FROM Users WHERE UserId = ?;", userId , function (err, row) { + dbs[currentCurveId].get("SELECT Uid FROM Users WHERE UserId = ?;", userId , function (err, row) { if (row == undefined) { // user not found in DB release(); - returnError(enum_errorCodes.user_not_found, "Post SPk but "+userId+" not found in db"); + returnError(currentCurveId, enum_errorCodes.user_not_found, "Post SPk but "+userId+" not found in db"); } else { - var Uid = row['Uid']; + let Uid = row['Uid']; - db.run("UPDATE Users SET SPk = ?, SPk_sig = ?, SPk_id = ? WHERE Uid = ?;", [SPk, Sig, SPk_id, Uid], function(errInsert){ + dbs[currentCurveId].run("UPDATE Users SET SPk = ?, SPk_sig = ?, SPk_id = ? WHERE Uid = ?;", [SPk, Sig, SPk_id, Uid], function(errInsert){ release(); if (errInsert == null) { returnOk(returnHeader); } else { console.log("INSERT failed err is "); console.log(errInsert); - returnError(enum_errorCodes.db_error, "Error while trying to insert SPK for user "+userId+". Backend says :"+errInsert); + returnError(currentCurveId, enum_errorCodes.db_error, "Error while trying to insert SPK for user "+userId+". Backend says :"+errInsert); } }); } }); }); - break; + }break; /* Post OPks : OPk number < uint16_t big endian: 2 bytes> | (OPk <ECDH public key size> | OPk id <uint32_t big endian: 4 bytes> ){OPk number} */ - case enum_messageTypes.postOPks: + case enum_messageTypes.postOPks:{ console.log("Got a postOPks Message from "+userId); // get the OPks number in the first message bytes(unsigned int 16 in big endian) - var bufferIndex = X3DH_headerSize; - var OPk_number = body.readUInt16BE(bufferIndex); - var x3dh_expectedSize = 2 + OPk_number*(keySizes[curveId]['OPk'] + 4); // read the public key + let bufferIndex = X3DH_headerSize; + let OPk_number = body.readUInt16BE(bufferIndex); + let x3dh_expectedSize = 2 + OPk_number*(keySizes[currentCurveId]['OPk'] + 4); // read the public key if (body.length<X3DH_headerSize + x3dh_expectedSize) { - returnError(enum_errorCodes.bad_size, "post OPK packet is expexted to be "+(X3DH_headerSize+x3dh_expectedSize)+" bytes, but we got "+body.length+" bytes"); + returnError(currentCurveId, enum_errorCodes.bad_size, "post OPK packet is expexted to be "+(X3DH_headerSize+x3dh_expectedSize)+" bytes, but we got "+body.length+" bytes"); return; } bufferIndex+=2; // point to the beginning of first key @@ -517,55 +497,55 @@ https.createServer(options, (req, res) => { console.log("It contains "+OPk_number+" keys"); if ((lime_max_opk_per_device > 0) && (OPk_number > lime_max_opk_per_device)) { // too much OPk, reject registration - returnError(enum_errorCodes.resource_limit_reached, userId+" is trying to insert "+OPk_number+" OPks but server has a limit of "+lime_max_opk_per_device); + returnError(currentCurveId, enum_errorCodes.resource_limit_reached, userId+" is trying to insert "+OPk_number+" OPks but server has a limit of "+lime_max_opk_per_device); return; } // check we have a matching user in DB lock.writeLock(function (release) { - db.get("SELECT Uid FROM Users WHERE UserId = ?;", userId , function (err, row) { + dbs[currentCurveId].get("SELECT Uid FROM Users WHERE UserId = ?;", userId , function (err, row) { if (row == undefined) { // user not found in DB release(); - returnError(enum_errorCodes.user_not_found, "Post OPks but "+userId+" not found in db"); + returnError(currentCurveId, enum_errorCodes.user_not_found, "Post OPks but "+userId+" not found in db"); } else { - var Uid = row['Uid']; + let Uid = row['Uid']; // Check we won't get over the maximum OPks allowed if (lime_max_opk_per_device > 0) { - db.get("SELECT COUNT(OPK_id) as OPk_count FROM Users as u INNER JOIN OPk as o ON u.Uid=o.Uid WHERE UserId = ?;", userId, function (err, row) { + dbs[currentCurveId].get("SELECT COUNT(OPK_id) as OPk_count FROM Users as u INNER JOIN OPk as o ON u.Uid=o.Uid WHERE UserId = ?;", userId, function (err, row) { if (err) { release(); - returnError(enum_errorCodes.db_error, " Database error in postOPks by "+userId+" : "+err2); + returnError(currentCurveId, enum_errorCodes.db_error, " Database error in postOPks by "+userId+" : "+err2); return; } - var OPk_count = 0; + let OPk_count = 0; if (row != undefined) { OPk_count = row['OPk_count']; } if (OPk_count+OPk_number > lime_max_opk_per_device) { // too much OPks release(); - returnError(enum_errorCodes.resource_limit_reached, userId+" is trying to insert "+OPk_number+" OPks but server has a limit of "+lime_max_opk_per_device+" and it already holds "+OPk_count); + returnError(currentCurveId, enum_errorCodes.resource_limit_reached, userId+" is trying to insert "+OPk_number+" OPks but server has a limit of "+lime_max_opk_per_device+" and it already holds "+OPk_count); return; } // parse all OPks to be inserted - var OPks_param = []; + let OPks_param = []; for (let i = 0; i < OPk_number; i++) { - var OPk = body.slice(bufferIndex, bufferIndex + keySizes[curveId]['OPk']); - bufferIndex += keySizes[curveId]['OPk']; - var OPk_id = body.readUInt32BE(bufferIndex); // OPk id is a 32 bits unsigned integer in Big endian + let OPk = body.slice(bufferIndex, bufferIndex + keySizes[currentCurveId]['OPk']); + bufferIndex += keySizes[currentCurveId]['OPk']; + let OPk_id = body.readUInt32BE(bufferIndex); // OPk id is a 32 bits unsigned integer in Big endian bufferIndex += 4; OPks_param.push([Uid, OPk, OPk_id]); } // bulk insert of OPks - var stmt_ran = 0; - var stmt_success = 0; - var stmt_err_message = ''; - db.run("begin transaction"); - var stmt = db.prepare("INSERT INTO OPk(Uid, OPk, OPk_id) VALUES(?,?,?);") + let stmt_ran = 0; + let stmt_success = 0; + let stmt_err_message = ''; + dbs[currentCurveId].run("begin transaction"); + let stmt = dbs[currentCurveId].prepare("INSERT INTO OPk(Uid, OPk, OPk_id) VALUES(?,?,?);") for (let i=0; i<OPks_param.length; i++) { param = OPks_param[i]; stmt.run(param, function(stmt_err, stmt_res){ // callback is called for each insertion, so we shall count errors and success @@ -577,11 +557,11 @@ https.createServer(options, (req, res) => { } if (stmt_ran == OPk_number) { // and react only when we reach correct count if (stmt_ran != stmt_success) { - db.run("rollback") + dbs[currentCurveId].run("rollback") release(); - returnError(enum_errorCodes.db_error, "Error while trying to insert OPk for user "+userId+". Backend says :"+stmt_err); + returnError(currentCurveId, enum_errorCodes.db_error, "Error while trying to insert OPk for user "+userId+". Backend says :"+stmt_err); } else { - db.run("commit") + dbs[currentCurveId].run("commit") release(); returnOk(returnHeader); } @@ -593,21 +573,21 @@ https.createServer(options, (req, res) => { } else { // Note : this code shall be factorized // parse all OPks to be inserted - var OPks_param = []; + let OPks_param = []; for (let i = 0; i < OPk_number; i++) { - var OPk = body.slice(bufferIndex, bufferIndex + keySizes[curveId]['OPk']); - bufferIndex += keySizes[curveId]['OPk']; - var OPk_id = body.readUInt32BE(bufferIndex); // OPk id is a 32 bits unsigned integer in Big endian + let OPk = body.slice(bufferIndex, bufferIndex + keySizes[currentCurveId]['OPk']); + bufferIndex += keySizes[currentCurveId]['OPk']; + let OPk_id = body.readUInt32BE(bufferIndex); // OPk id is a 32 bits unsigned integer in Big endian bufferIndex += 4; OPks_param.push([Uid, OPk, OPk_id]); } // bulk insert of OPks - var stmt_ran = 0; - var stmt_success = 0; - var stmt_err_message = ''; - db.run("begin transaction"); - var stmt = db.prepare("INSERT INTO OPk(Uid, OPk, OPk_id) VALUES(?,?,?);") + let stmt_ran = 0; + let stmt_success = 0; + let stmt_err_message = ''; + dbs[currentCurveId].run("begin transaction"); + let stmt = dbs[currentCurveId].prepare("INSERT INTO OPk(Uid, OPk, OPk_id) VALUES(?,?,?);") for (let i=0; i<OPks_param.length; i++) { param = OPks_param[i]; stmt.run(param, function(stmt_err, stmt_res){ // callback is called for each insertion, so we shall count errors and success @@ -619,11 +599,11 @@ https.createServer(options, (req, res) => { } if (stmt_ran == OPk_number) { // and react only when we reach correct count if (stmt_ran != stmt_success) { - db.run("rollback") + dbs[currentCurveId].run("rollback") release(); - returnError(enum_errorCodes.db_error, "Error while trying to insert OPk for user "+userId+". Backend says :"+stmt_err); + returnError(currentCurveId, enum_errorCodes.db_error, "Error while trying to insert OPk for user "+userId+". Backend says :"+stmt_err); } else { - db.run("commit") + dbs[currentCurveId].run("commit") release(); returnOk(returnHeader); } @@ -634,7 +614,7 @@ https.createServer(options, (req, res) => { } }); }); - break; + }break; /* peerBundle : bundle Count < 2 bytes unsigned Big Endian> | * ( deviceId Size < 2 bytes unsigned Big Endian > | deviceId @@ -645,12 +625,12 @@ https.createServer(options, (req, res) => { * (OPk <ECDH Public Key Length> | OPk id <4 bytes>){0,1 in accordance to flag} * ) { bundle Count} */ - case enum_messageTypes.getPeerBundle: + case enum_messageTypes.getPeerBundle:{ function buildPeerBundlePacket(peersBundle) { let peersBundleBuffer = Buffer.allocUnsafe(X3DH_headerSize+2); peersBundleBuffer.writeUInt8(X3DH_protocolVersion, 0); peersBundleBuffer.writeUInt8(enum_messageTypes.peerBundle, 1); - peersBundleBuffer.writeUInt8(curveId, 2); + peersBundleBuffer.writeUInt8(currentCurveId, 2); peersBundleBuffer.writeUInt16BE(peersBundle.length, 3); // peers bundle count on 2 bytes in Big Endian for (let i=0; i<peersBundle.length; i++) { @@ -687,18 +667,18 @@ https.createServer(options, (req, res) => { // first parse the message - var bufferIndex = X3DH_headerSize; - var peersCount = body.readUInt16BE(bufferIndex); // 2 bytes BE unsigned int : number of devices uri + let bufferIndex = X3DH_headerSize; + let peersCount = body.readUInt16BE(bufferIndex); // 2 bytes BE unsigned int : number of devices uri if (peersCount == 0) { - returnError(enum_errorCodes.bad_request, "Ask for peer Bundles but no device id given"); + returnError(currentCurveId, enum_errorCodes.bad_request, "Ask for peer Bundles but no device id given"); release(); } bufferIndex+=2; - var peersBundle = []; + let peersBundle = []; for (let i=0; i<peersCount; i++) { - var IdLength = body.readUInt16BE(bufferIndex); // 2 bytes BE unsigned int : length of the following id string + let IdLength = body.readUInt16BE(bufferIndex); // 2 bytes BE unsigned int : length of the following id string bufferIndex+=2; peersBundle.push([body.toString('utf8', bufferIndex, bufferIndex+IdLength)]); // create element of peersBundle as an array as we will then push the keys on it bufferIndex+=IdLength; @@ -710,13 +690,13 @@ https.createServer(options, (req, res) => { lock.writeLock(function (release) { console.log("Process a getPeerBundle Message from "+userId); // Try to access all requested values - var queries_ran = 0; - var queries_success = 0; - var queries_err_message = ''; + let queries_ran = 0; + let queries_success = 0; + let queries_err_message = ''; for (let i=0; i<peersCount; i++) { // left join as we may not have any OPk but shall cope with it - db.get("SELECT u.Ik, u.SPk, u.SPk_id, u.SPk_sig, o.OPk, o.OPk_id, o.id FROM Users as u LEFT JOIN OPk as o ON u.Uid=o.Uid WHERE UserId = ? AND u.SPk IS NOT NULL LIMIT 1;", peersBundle[i][0] , function (err, row) { + dbs[currentCurveId].get("SELECT u.Ik, u.SPk, u.SPk_id, u.SPk_sig, o.OPk, o.OPk_id, o.id FROM Users as u LEFT JOIN OPk as o ON u.Uid=o.Uid WHERE UserId = ? AND u.SPk IS NOT NULL LIMIT 1;", peersBundle[i][0] , function (err, row) { queries_ran++; if (err) { queries_err_message +=' ## get bundle for user '+peersBundle[i]+" error : "+err; @@ -738,7 +718,7 @@ https.createServer(options, (req, res) => { console.log("Ok we retrieved OPk "+row['id']+" from table, we must remove it"); //NOTE: in real situation we have to find a way to insure the value wasn't also read by an other request queries_ran--; // this query is not over: step back - db.run("DELETE FROM OPk WHERE id = ?;", [row['id']], function(errDelete){ + dbs[currentCurveId].run("DELETE FROM OPk WHERE id = ?;", [row['id']], function(errDelete){ queries_ran++; if (errDelete == null) { queries_success++; @@ -748,7 +728,7 @@ https.createServer(options, (req, res) => { if (queries_ran == peersCount) { if (queries_ran != queries_success) { - returnError(enum_errorCodes.db_error, "Error while trying to get peers bundles :"+queries_err_message); + returnError(currentCurveId, enum_errorCodes.db_error, "Error while trying to get peers bundles :"+queries_err_message); } else { // build the peerBundle Message buildPeerBundlePacket(peersBundle); // this one build and return the buffer @@ -763,7 +743,7 @@ https.createServer(options, (req, res) => { if (queries_ran == peersCount) { if (queries_ran != queries_success) { - returnError(enum_errorCodes.db_error, "Error while trying to get peers bundles :"+queries_err_message); + returnError(currentCurveId, enum_errorCodes.db_error, "Error while trying to get peers bundles :"+queries_err_message); } else { // build the peerBundle Message buildPeerBundlePacket(peersBundle); // this one build and return the buffer @@ -775,22 +755,22 @@ https.createServer(options, (req, res) => { }); // writeLock - break; + }break; /* selfOPks : OPKs Id Count < 2 bytes unsigned Big Endian> | * (OPk id <4 bytes>){ OPks Id Count} */ - case enum_messageTypes.getSelfOPks: + case enum_messageTypes.getSelfOPks:{ console.log("Process a getSelfOPks Message from "+userId); // check we have a matching user in DB - db.get("SELECT Uid FROM Users WHERE UserId = ?;", userId , function (err, row) { + dbs[currentCurveId].get("SELECT Uid FROM Users WHERE UserId = ?;", userId , function (err, row) { if (row == undefined) { // user not found in DB - returnError(enum_errorCodes.user_not_found, "Get Self OPks but "+userId+" not found in db"); + returnError(currentCurveId, enum_errorCodes.user_not_found, "Get Self OPks but "+userId+" not found in db"); } else { - db.all("SELECT o.OPk_id as OPk_id FROM Users as u INNER JOIN OPk as o ON u.Uid=o.Uid WHERE UserId = ?;", userId, function (err, rows) { + dbs[currentCurveId].all("SELECT o.OPk_id as OPk_id FROM Users as u INNER JOIN OPk as o ON u.Uid=o.Uid WHERE UserId = ?;", userId, function (err, rows) { if (err) { - returnError(enum_errorCodes.db_error, " Database error in getSelfOPks by "+userId+" : "+err); + returnError(currentCurveId, enum_errorCodes.db_error, " Database error in getSelfOPks by "+userId+" : "+err); return; } @@ -798,7 +778,7 @@ https.createServer(options, (req, res) => { let selfOPKsBuffer = Buffer.allocUnsafe(X3DH_headerSize+2); selfOPKsBuffer.writeUInt8(X3DH_protocolVersion, 0); selfOPKsBuffer.writeUInt8(enum_messageTypes.selfOPks, 1); - selfOPKsBuffer.writeUInt8(curveId, 2); + selfOPKsBuffer.writeUInt8(currentCurveId, 2); if (rows == undefined || rows.length == 0) { // no Id founds selfOPKsBuffer.writeUInt16BE(0, 3); // peers bundle count on 2 bytes in Big Endian @@ -815,10 +795,10 @@ https.createServer(options, (req, res) => { }); } }); - break; + }break; default: - returnError(enum_errorCodes.bad_message_type, "Unknown message type "+messageType); + returnError(currentCurveId, enum_errorCodes.bad_message_type, "Unknown message type "+messageType); break; } }); -- GitLab From 37da46c71b1b3fe03217a815c8fc507714ba04d3 Mon Sep 17 00:00:00 2001 From: johan pascal <johan.pascal@belledonne-communications.com> Date: Tue, 14 Jan 2025 00:20:43 +0100 Subject: [PATCH 5/5] Drop support for C and java API --- CMakeLists.txt | 24 - README.md | 23 +- include/CMakeLists.txt | 4 - include/lime/lime_ffi.h | 447 ------------ src/CMakeLists.txt | 13 +- src/java/CMakeLists.txt | 43 -- .../org/linphone/lime/LimeCallbackReturn.java | 52 -- src/java/org/linphone/lime/LimeCurveId.java | 36 - .../linphone/lime/LimeEncryptionPolicy.java | 39 - src/java/org/linphone/lime/LimeException.java | 25 - src/java/org/linphone/lime/LimeManager.java | 343 --------- .../org/linphone/lime/LimeOutputBuffer.java | 26 - .../linphone/lime/LimePeerDeviceStatus.java | 69 -- .../org/linphone/lime/LimePostToX3DH.java | 35 - .../org/linphone/lime/LimeStatusCallback.java | 33 - src/java/org/linphone/lime/RecipientData.java | 53 -- src/jni/LICENSE.txt | 13 - src/jni/advanced_ownership.hpp | 112 --- src/jni/array.hpp | 147 ---- src/jni/arraylike.hpp | 41 -- src/jni/boxing.hpp | 159 ----- src/jni/class.hpp | 137 ---- src/jni/constructor.hpp | 15 - src/jni/errors.hpp | 119 ---- src/jni/field.hpp | 27 - src/jni/functions.hpp | 665 ------------------ src/jni/jni.hpp | 26 - src/jni/make.hpp | 12 - src/jni/method.hpp | 31 - src/jni/native_method.hpp | 377 ---------- src/jni/npe.hpp | 24 - src/jni/object.hpp | 153 ---- src/jni/ownership.hpp | 224 ------ src/jni/static_field.hpp | 27 - src/jni/static_method.hpp | 31 - src/jni/string.hpp | 35 - src/jni/string_conversion.hpp | 21 - src/jni/tagging.hpp | 131 ---- src/jni/traits.hpp | 34 - src/jni/type_signature.hpp | 89 --- src/jni/typed_methods.hpp | 147 ---- src/jni/types.hpp | 97 --- src/jni/unique.hpp | 220 ------ src/jni/weak_reference.hpp | 40 -- src/jni/wrapping.hpp | 152 ---- src/lime_ffi.cpp | 481 ------------- src/lime_jni.cpp | 551 --------------- 47 files changed, 12 insertions(+), 5591 deletions(-) delete mode 100644 include/lime/lime_ffi.h delete mode 100644 src/java/CMakeLists.txt delete mode 100644 src/java/org/linphone/lime/LimeCallbackReturn.java delete mode 100644 src/java/org/linphone/lime/LimeCurveId.java delete mode 100644 src/java/org/linphone/lime/LimeEncryptionPolicy.java delete mode 100644 src/java/org/linphone/lime/LimeException.java delete mode 100644 src/java/org/linphone/lime/LimeManager.java delete mode 100644 src/java/org/linphone/lime/LimeOutputBuffer.java delete mode 100644 src/java/org/linphone/lime/LimePeerDeviceStatus.java delete mode 100644 src/java/org/linphone/lime/LimePostToX3DH.java delete mode 100644 src/java/org/linphone/lime/LimeStatusCallback.java delete mode 100644 src/java/org/linphone/lime/RecipientData.java delete mode 100644 src/jni/LICENSE.txt delete mode 100644 src/jni/advanced_ownership.hpp delete mode 100644 src/jni/array.hpp delete mode 100644 src/jni/arraylike.hpp delete mode 100644 src/jni/boxing.hpp delete mode 100644 src/jni/class.hpp delete mode 100644 src/jni/constructor.hpp delete mode 100644 src/jni/errors.hpp delete mode 100644 src/jni/field.hpp delete mode 100644 src/jni/functions.hpp delete mode 100644 src/jni/jni.hpp delete mode 100644 src/jni/make.hpp delete mode 100644 src/jni/method.hpp delete mode 100644 src/jni/native_method.hpp delete mode 100644 src/jni/npe.hpp delete mode 100644 src/jni/object.hpp delete mode 100644 src/jni/ownership.hpp delete mode 100644 src/jni/static_field.hpp delete mode 100644 src/jni/static_method.hpp delete mode 100644 src/jni/string.hpp delete mode 100644 src/jni/string_conversion.hpp delete mode 100644 src/jni/tagging.hpp delete mode 100644 src/jni/traits.hpp delete mode 100644 src/jni/type_signature.hpp delete mode 100644 src/jni/typed_methods.hpp delete mode 100644 src/jni/types.hpp delete mode 100644 src/jni/unique.hpp delete mode 100644 src/jni/weak_reference.hpp delete mode 100644 src/jni/wrapping.hpp delete mode 100644 src/lime_ffi.cpp delete mode 100644 src/lime_jni.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d79432c..dc0a1cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,19 +30,11 @@ option(ENABLE_CURVE448 "Enable support of Curve 448(goldilock)." YES) option(ENABLE_UNIT_TESTS "Enable compilation of unit tests." YES) option(ENABLE_DOC "Enable API documentation generation." NO) option(ENABLE_PROFILING "Enable profiling, GCC only" NO) -option(ENABLE_C_INTERFACE "Enable support of C89 foreign function interface" NO) -option(ENABLE_JNI "Enable support of Java foreign function interface" NO) option(ENABLE_PACKAGE_SOURCE "Create 'package_source' target for source archive making" OFF) option(ENABLE_PQCRYPTO "Enable Post Quantum Cryptography key agreements algorithms" NO) set(LANGUAGES_LIST CXX) -if(ENABLE_C_INTERFACE) - set(LANGUAGES_LIST ${LANGUAGES_LIST} C) -endif() -if(ENABLE_JNI) - set(LANGUAGES_LIST ${LANGUAGES_LIST} Java) -endif() project(Lime VERSION 5.4.0 LANGUAGES ${LANGUAGES_LIST}) @@ -130,22 +122,6 @@ if(ENABLE_CURVE448) message(STATUS "Support Curve 448") endif() -if(ENABLE_C_INTERFACE) - add_definitions("-DFFI_ENABLED") - message(STATUS "Provide C89 interface") -endif() - -if(ENABLE_JNI) - message(STATUS "Provide JNI interface") - if(NOT ANDROID) - find_package(JNI REQUIRED) - if(JNI_FOUND) - message (STATUS "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}") - message (STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}") - endif() - endif() -endif() - if(ENABLE_PQCRYPTO) add_definitions("-DHAVE_BCTBXPQ") message(STATUS "Building with Post Quantum Key Encapsulation") diff --git a/README.md b/README.md index 9727e33..be9dea7 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ Lime ======= -LIME is an end-to-end encryption library for one-to-one and group instant messaging, allowing users to exchange messages privately and asynchronously. It uses modern ciphering curve X448 and double ratchet algorithm for perfect forward secrecy. +LIME is an end-to-end encryption library for one-to-one and group instant messaging, allowing users to exchange messages privately and asynchronously. LIME is composed of a portable client library coupled with a public key server developed by Belledonne Communications to allow end-to-end encryption for messaging, without having to exchange cryptographic keys simultaneously. -The library exposes a C, C++, Python and Java API for easy integration in mobile and desktop environments. +The library exposes a C++ API for easy integration in mobile and desktop environments. LIME supports multiple devices per user and multiple users per device. @@ -19,15 +19,13 @@ license (closed source). Copyright © Belledonne Communications SARL -The content of *src/jni* directory Copyright (c) 2016 Mapbox are covered by its respective license, -see *src/jni/LICENSE.txt* - -The public key server (LIME server) is not part of this software package, and is only available under a proprietary license. +The public key server (LIME server) is not part of this software package but can be found on the [lime server repository](https://gitlab.linphone.org/BC/public/lime-server) Dependencies ------------ -- *bctoolbox[2]* : portability layer, built with Elliptic Curve Cryptography -- *soci-sqlite3* : Db access +- *bctoolbox[1]* : portability layer, built with Elliptic Curve Cryptography +- *soci-sqlite[2]* : Db access +- *postquantumcryptoengine[3]* : abstraction layer to Kyber and MLKEM Build instructions @@ -104,13 +102,12 @@ Options - `ENABLE_STRICT` : build with strict complier flags e.g. `-Wall -Werror` (default YES) - `ENABLE_CURVE25519` : Enable support of Curve 25519 (default YES) - `ENABLE_CURVE448` : Enable support of Curve 448 (default YES) +- `ENABLE_PQCRYPTO' : Enable Post Quantum Cryptography key agreements algorithms(default NO) - `ENABLE_PROFILING` : Enable code profiling for GCC (default NO) -- `ENABLE_C_INTERFACE` : Enable support of C89 foreign function interface (default NO) -- `ENABLE_JNI` : Enable support of Java foreign function interface (default NO) - `ENABLE_DOC` : Enable documenation generation, requires Doxygen (default NO) ------------------ -- [1] linphone-desktop: https://gitlab.linphone.org/BC/public/linphone-desktop.git -- [2] bctoolbox: https://gitlab.linphone.org/BC/public/bctoolbox.git -- [3] linphone-sdk: https://gitlab.linphone.org/BC/public/linphone-sdk.git +- [1] bctoolbox: https://gitlab.linphone.org/BC/public/bctoolbox.git +- [2] soci: https://gitlab.linphone.org/BC/public/external/soci +- [3] postquantumcryptoengine: https://gitlab.linphone.org/BC/public/postquantumcryptoengine diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index fb7fd6a..c036bb6 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -24,10 +24,6 @@ set(HEADER_FILES lime.hpp ) -if (ENABLE_C_INTERFACE) - set(HEADER_FILES ${HEADER_FILES} lime_ffi.h) -endif() - set(LIME_HEADER_FILES ) foreach(HEADER_FILE ${HEADER_FILES}) list(APPEND LIME_HEADER_FILES "${CMAKE_CURRENT_LIST_DIR}/lime/${HEADER_FILE}") diff --git a/include/lime/lime_ffi.h b/include/lime/lime_ffi.h deleted file mode 100644 index d3c9342..0000000 --- a/include/lime/lime_ffi.h +++ /dev/null @@ -1,447 +0,0 @@ -/** - @file lime_ffi.h - - @brief This header exports lime's functionality via a C89 interface. - - General rules of this API to make life easier to anyone trying to use it - from another langage: - - all interaction are done via pointer to opaque structure - - use only simple types: - - size_t for all buffer or array size - - const char * NULL terminated strings - - uint8_t * for binary buffers - - no ownership of memory transfers across the API boundary.\n - The API read data from const pointers and write output to buffers allocated by the caller. - - when exporting a binary blob, the function takes a pointer to the output buffer and a read/write pointer to the length.\n - If the size of the provided buffer is insufficient, an error is returned. - - @warning Check carefully the lime_ffi_decrypt function's documentation as an output buffer too small on this one mean you would loose your decrypted message forever. - - @author Johan Pascal - - @copyright Copyright (C) 2018 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -#ifndef lime_ffi_hpp -#define lime_ffi_hpp - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdlib.h> -#include <stdint.h> - -typedef struct lime_manager_struct* lime_manager_t; - -typedef struct lime_ffi_data_struct* lime_ffi_data_t; - -enum LIME_FFI_ERROR { - LIME_FFI_SUCCESS = 0, - LIME_FFI_INVALID_CURVE_ARGUMENT = -1, - LIME_FFI_INTERNAL_ERROR = -2, - LIME_FFI_OUTPUT_BUFFER_TOO_SMALL = -3, - LIME_FFI_USER_NOT_FOUND = -4 -}; - -/** Identifies the elliptic curve used in lime, the values assigned are used in localStorage and X3DH server - * so do not modify it or we'll loose sync with existing DB and X3DH server - */ -enum lime_ffi_CurveId { - lime_ffi_CurveId_unset = 0, /**< used as default to detected incorrect behavior */ - lime_ffi_CurveId_c25519 = 1, /**< Curve 25519 */ - lime_ffi_CurveId_c448 = 2 /**< Curve 448-goldilocks */ -}; - -/** Manage the encryption policy : how is the user's plaintext encrypted */ -enum lime_ffi_EncryptionPolicy { - lime_ffi_EncryptionPolicy_DRMessage, /**< the plaintext input is encrypted inside the Double Ratchet message (each recipient get a different encryption): not optimal for messages with numerous recipient */ - lime_ffi_EncryptionPolicy_cipherMessage, /**< the plaintext input is encrypted with a random key and this random key is encrypted to each participant inside the Double Ratchet message(for a single recipient the overhead is 48 bytes) */ - lime_ffi_EncryptionPolicy_optimizeUploadSize, /**< optimize upload size: encrypt in DR message if plaintext is short enougth to beat the overhead introduced by cipher message scheme, otherwise use cipher message. Selection is made on upload size only. This is the default policy used */ - lime_ffi_EncryptionPolicy_optimizeGlobalBandwidth /**< optimize bandwith usage: encrypt in DR message if plaintext is short enougth to beat the overhead introduced by cipher message scheme, otherwise use cipher message. Selection is made on uploadand download (from server to recipients) sizes added. */ -}; - -/** - * A peer device status returned after encrypt, decrypt or when directly asking for the peer device status to spot new devices and give information on our trust on this device - * The values explicitely mapped to specific integers(untrusted, trusted, unsafe) are stored in local storage as integer - * Do not modify the mapping or we will loose backward compatibility with existing databases - */ -enum lime_ffi_PeerDeviceStatus { - lime_ffi_PeerDeviceStatus_untrusted=0, /**< we know this device but do not trust it, that information shall be displayed to the end user, a colour code shall be enough */ - lime_ffi_PeerDeviceStatus_trusted=1, /**< this peer device already got its public identity key validated, that information shall be displayed to the end user too */ - lime_ffi_PeerDeviceStatus_unsafe=2, /**< this status is a helper for the library user. It is used only by the peerDeviceStatus accessor functions */ - lime_ffi_PeerDeviceStatus_fail, /**< when returned by decrypt : we could not decrypt the incoming message\n - when returned by encrypt in the peerStatus: we could not encrypt to this recipient(probably because it does not published keys on the X3DH server) */ - lime_ffi_PeerDeviceStatus_unknown /**< when returned after encryption or decryption, means it is the first time we communicate with this device (and thus create a DR session with it)\n - when returned by a get_peerDeviceStatus: this device is not in localStorage */ -}; - -/** what a Lime callback could possibly say */ -enum lime_ffi_CallbackReturn { - lime_ffi_CallbackReturn_success, /**< operation completed successfully */ - lime_ffi_CallbackReturn_fail /**< operation failed, we shall have an explanation string too */ -}; - -/** @brief The encrypt function input/output data structure - * - * give a recipient GRUU and get it back with the header which must be sent to recipient with the cipher text - */ -typedef struct { - char *deviceId; /**< input: recipient deviceId (shall be GRUU) */ - enum lime_ffi_PeerDeviceStatus peerStatus; /**< output: after encrypt calls back, it will hold the status of this peer device:\n - - lime_ffi_PeerDeviceStatus_unknown: first interaction with this device) - - lime_ffi_PeerDeviceStatus_untrusted: device is kown but we never confirmed its identity public key - - lime_ffi_PeerDeviceStatus_trusted: we already confirmed this device identity public key - - lime_ffi_PeerDeviceStatus_fail: we could not encrypt for this device, probably because it never published its keys on the X3DH server */ - uint8_t *DRmessage; /**< output: after encrypt calls back, it will hold the Double Ratchet message targeted to the specified recipient. */ - size_t DRmessageSize; /**< input/output: size off the DRmessage buffer at input, size of written data as output */ -} lime_ffi_RecipientData_t; - -/** @brief Callback use to give a status on asynchronous operation - * - * it returns a code and may return a string (could actually be empty) to detail what's happening - * callback is used on every operation possibly involving a connection to X3DH server: create_user, delete_user, encrypt and update - * - * @param[in] userData pointer to user defined data structure passed back to him - * @param[in] status success or fail - * @param[in] message in case of failure, an explanation, it may be empty - */ -typedef void (*lime_ffi_Callback)(void *userData, const enum lime_ffi_CallbackReturn status, const char *message); - -/** - * @brief Post a message to the X3DH server - * - * this function prototype is used to post data to the X3DH server - * The response must be sent back to the lime engine using the lime_ffi_processX3DHServerResponse function - * - * @param[in] userData pointer given when registering the callback - * @param[in] limeData pointer to an opaque lime internal structure that must then be forwarded with the server response - * @param[in] url X3DH server's URL - * @param[in] from User identification on X3DH server (which shall challenge for password digest, this is not however part of lime) - * @param[in] message The message to post to the X3DH server - */ -typedef void (*lime_ffi_X3DHServerPostData)(void *userData, lime_ffi_data_t limeData, const char *url, const char *from, - const uint8_t *message, const size_t message_size); - - - -/** - * @brief Forward X3DH server response to the lime engine - * - * @param[in] limeData A pointer to an opaque structure used internally (provided by the X3DHServerPostData function) - * @param[in] code The response code given by X3DH server, connection is made through https, so we expect 200 for Ok - * @param[in] response binary buffered server response - * @param[in] response_size size of previous buffer - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_processX3DHServerResponse(lime_ffi_data_t limeData, const int code, const uint8_t *response, const size_t response_size); - -/** - * @brief Initialise a Lime Manager, only one per end-point is required. - * - * @param[out] manager pointer to the opaque structure used to interact with lime - * @param[in] db string used to access DB (shall be filename for sqlite3), directly forwarded to SOCI session opening - * @param[in] X3DH_post_data A function to send data to the X3DH server. The server response must be forwarded to lime using the lime_ffi_processX3DHServerResponse function - * @param[in] userData pointer passed back to the X3DH_post_data callback - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_manager_init(lime_manager_t * const manager, const char *db, const lime_ffi_X3DHServerPostData X3DH_post_data, void *userData); - -/** - * @brief Destroy the internal structure used to interact with lime - * - * @param[in,out] manager pointer to the opaque structure used to interact with lime - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_manager_destroy(lime_manager_t manager); - - -/** - * @brief Insert a lime user in local base and publish him on the X3DH server - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] localDeviceId Identify the local user acount to use, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * @param[in] x3dhServerUrl The complete url(including port) of the X3DH key server. It must connect using HTTPS. Example: https://sip5.linphone.org:25519 - * @param[in] curve Choice of elliptic curve to use as base for ECDH and EdDSA operation involved. Can be lime_ffi_CurveId_c25519 or lime_ffi_CurveId_c448. - * @param[in] OPkInitialBatchSize Number of OPks in the first batch uploaded to X3DH server - * @param[in] callback This operation contact the X3DH server and is thus asynchronous, when server responds,\n - * this callback will be called giving the exit status and an error message in case of failure - * @param[in] callbackUserData this pointer will be forwarded to the callback as first parameter - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_create_user(lime_manager_t manager, const char *localDeviceId, - const char *x3dhServerUrl, const enum lime_ffi_CurveId curve, const uint16_t OPkInitialBatchSize, - const lime_ffi_Callback callback, void *callbackUserData); - -/** - * @brief Delete a user from local database and from the X3DH server - * - * if specified localDeviceId is not found in local Storage, return an error - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] localDeviceId Identify the local user acount to use, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * @param[in] callback This operation contact the X3DH server and is thus asynchronous, when server responds, - * this callback will be called giving the exit status and an error message in case of failure - * @param[in] callbackUserData this pointer will be forwarded to the callback as first parameter - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_delete_user(lime_manager_t manager, const char *localDeviceId, const lime_ffi_Callback callback, void *callbackUserData); - -/** - * @brief Check if a user is present and active in local storage - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] localDeviceId used to identify which local account looking up, shall be the GRUU (Null terminated string) - * - * @return LIME_FFI_SUCCESS if the user is active in the local storage, LIME_FFI_USER_NOT_FOUND otherwise - */ -int lime_ffi_is_user(lime_manager_t manager, const char *localDeviceId); - -/** - * @brief Compute the maximum buffer sizes for the encryption outputs: DRmessage and cipherMessage - * - * @param[in] plainMessageSize size of the plain message to be encrypted - * @param[in] curve Choice of elliptic curve to use as base for ECDH and EdDSA operation involved. Can be lime_ffi_CurveId_c25519 or lime_ffi_CurveId_c448. - * @param[out] DRmessageSize maximum size of the DRmessage produced by the encrypt function - * @param[out] cipherMessageSize maximum size of the cipherMessage produced by the encrypt function - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_encryptOutBuffersMaximumSize(const size_t plainMessageSize, const enum lime_ffi_CurveId curve, size_t *DRmessageSize, size_t *cipherMessageSize); - -/** - * @brief Encrypt a buffer (text or file) for a given list of recipient devices - * - * if specified localDeviceId is not found in local Storage, return an error - * - * Clarification on recipients: - * - * recipients information needed are a list of the device Id and one userId. The device Id shall be their GRUU while the userId is a sip:uri. - * - * recipient User Id is used to identify the actual intended recipient. Example: alice have two devices and is signed up on a conference having - * bob and claire as other members. The recipientUserId will be the conference sip:uri and device list will include: - * - alice other device - * - bob devices - * - claire devices - * If Alice write to Bob only, the recipientUserId will be bob sip:uri and recipient devices list : - * - alice other device - * - bob devices - * - * In all cases, the identified source of the message will be the localDeviceId - * - * If the X3DH server can't provide keys for a peer device, its status is set to fail and its DRmessageSize is 0. Other devices get their encrypted message - * If no peer device could get encrypted for all of them are missing keys on the X3DH server, the callback will be called with fail exit status - * - * @note all buffers are allocated by caller. If a buffer is too small to get the data, the function will return an error. - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] localDeviceId used to identify which local acount to use and also as the identified source of the message, shall be the GRUU - * @param[in] recipientUserId the Id of intended recipient, shall be a sip:uri of user or conference, is used as associated data to ensure no-one can mess with intended recipient - * @param[in] recipientUserIdSize the size of the previous buffer(this is used as Associated Data, so it could be actually anything) - * @param[in,out] recipients a list of RecipientData holding: - * - the recipient device Id(GRUU) - * - an allocated buffer large enough to store the DRmessage which must then be routed to that recipient - * - the size of this buffer, updated with the actual size written in it when the operation is completed(after callbackStatus is executed) - * - the peer Status. If peerStatus is set to fail, this entry is ignored otherwise the peerStatus is set by the encrypt, see lime_ffi_PeerDeviceStatus definition for details - * @param[in] recipientsSize how many recipients are in the recipients array - * @param[in] plainMessage a buffer holding the message to encrypt, can be text or data. - * @param[in] plainMessageSize size of the plainMessage buffer - * @param[out] cipherMessage points to the buffer to store the encrypted message which must be routed to all recipients(if one is produced, depends on encryption policy) - * @param[in,out] cipherMessageSize size of the cipherMessage buffer, is updated with the size of the actual data written in it - * @param[in] callback Performing encryption may involve the X3DH server and is thus asynchronous, when the operation is completed, - * this callback will be called giving the exit status and an error message in case of failure. - * @param[in] callbackUserData this pointer will be forwarded to the callback as first parameter - * @param[in] encryptionPolicy select how to manage the encryption: direct use of Double Ratchet message or encrypt in the cipher message and use the DR message to share the cipher message key - * default is optimized output size mode. - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_encrypt(lime_manager_t manager, const char *localDeviceId, - const uint8_t *const recipientUserId, const size_t recipientUserIdSize, - lime_ffi_RecipientData_t *const recipients, const size_t recipientsSize, - const uint8_t *const plainMessage, const size_t plainMessageSize, - uint8_t *const cipherMessage, size_t *cipherMessageSize, - const lime_ffi_Callback callback, void *callbackUserData, - enum lime_ffi_EncryptionPolicy encryptionPolicy); - - -/** - * @brief Decrypt the given message - * - * if specified localDeviceId is not found in local Storage, return an error - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] localDeviceId used to identify which local acount to use and also as the recipient device ID of the message, shall be the GRUU - * @param[in] recipientUserId the Id of intended recipient, shall be a sip:uri of user or conference, is used as associated data to ensure no-one can mess with intended recipient - * it is not necessarily the sip:uri base of the GRUU as this could be a message from alice first device intended to bob being decrypted on alice second device - * @param[in] recipientUserIdSize the size of the previous buffer(this is used as Associated Data, so it could be actually anything) - * @param[in] senderDeviceId Identify sender Device. This field shall be extracted from signaling data in transport protocol, is used to rebuild the authenticated data associated to the encrypted message - * @param[in] DRmessage Double Ratchet message targeted to current device - * @param[in] DRmessageSize DRmessage buffer size - * @param[in] cipherMessage when present (depends on encryption policy) holds a common part of the encrypted message. Set to NULL if not present in the incoming message. - * @param[in] cipherMessageSize cipherMessage buffer size(set to 0 if no cipherMessage is present in the incoming message) - * @param[out] plainMessage the output buffer: its size shall be MAX(cipherMessageSize, DRmessageSize) - * @param[in,out] plainMessageSize plainMessage buffer size, updated with the actual size of the data written - * - * @warning The plainMessage buffer must be large enough to store the decrypted message or we face the possibility to not ever be able to decrypt the message.(internal successful decryption will remove the ability to decrypt the same message again). To avoid problem the size of the plain message shall be MAX(cipherMessageSize, DRmessageSize) as: - * - The decrypted message is the same size of the encrypted one. - * - The encrypted message(not alone but we can afford the temporary usage of few dozens bytes) is stored either in cipherMessage or DRmessage depends on encrypter's choice - * - By allocating MAX(cipherMessageSize, DRmessageSize) bytes to the plainMessage buffer we ensure it can hold the decrypted message - * - * @return fail if we cannot decrypt the message, unknown when it is the first message we ever receive from the sender device, untrusted for known but untrusted sender device, or trusted if it is - */ -enum lime_ffi_PeerDeviceStatus lime_ffi_decrypt(lime_manager_t manager, const char *localDeviceId, - const uint8_t *const recipientUserId, const size_t recipientUserIdSize, - const char *senderDeviceId, - const uint8_t *const DRmessage, const size_t DRmessageSize, - const uint8_t *const cipherMessage, const size_t cipherMessageSize, - uint8_t *const plainMessage, size_t *plainMessageSize); - -/** - * @brief retrieve self Identity Key, an EdDSA formatted public key - * - * if specified localDeviceId is not found in local Storage, return an error - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] localDeviceId used to identify which local account we're dealing with, shall be the GRUU - * @param[out] Ik the EdDSA public identity key, formatted as in RFC8032 - * @param[in,out] IkSize size of the previous buffer, updated with the size of data actually written - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_get_selfIdentityKey(lime_manager_t manager, const char *localDeviceId, uint8_t *const Ik, size_t *IkSize); - -/** - * @brief set the peer device status flag in local storage: unsafe, trusted or untrusted. - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] peerDeviceId The device Id of peer, shall be its GRUU - * @param[in] Ik the EdDSA peer public identity key, formatted as in RFC8032 (optionnal, needed only if status is trusted) - * @param[in] IkSize size of the previous buffer - * @param[in] status value of flag to set: accepted values are trusted, untrusted, unsafe - * - * return an error if given key doesn't match the one present in local storage(if we have a key) - * if the status flag value is unexpected (not one of trusted, untrusted, unsafe), ignore the call - * if the status flag is unsafe or untrusted, ignore the value of Ik and call the version of this function without it - * - * if peer Device is not present in local storage and status is trusted or unsafe, it is added, if status is untrusted, it is just ignored - * - * General algorithm followed by the set_peerDeviceStatus functions - * - Status is valid? (not one of trusted, untrusted, unsafe)? No: return - * - status is trusted - * - We have Ik? -> No: return - * - Device is already in storage but Ik differs from the given one : exception - * - Insert/update in local storage - * - status is untrusted - * - Ik is ignored - * - Device already in storage? No: return - * - Device already in storage but current status is unsafe? Yes: return - * - update in local storage - * -status is unsafe - * - ignore Ik - * - insert/update the status. If inserted, insert an invalid Ik - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_set_peerDeviceStatus(lime_manager_t manager, const char *peerDeviceId, const uint8_t *const Ik, const size_t IkSize, enum lime_ffi_PeerDeviceStatus status); - -/** - * @brief get the status of a peer device: unknown, untrusted, trusted, unsafe - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] peerDeviceId The device Id of peer, shall be its GRUU - * - * @return unknown if the device is not in localStorage, untrusted, trusted or unsafe according to the stored value of peer device status flag otherwise - */ -enum lime_ffi_PeerDeviceStatus lime_ffi_get_peerDeviceStatus(lime_manager_t manager, const char *peerDeviceId); - - -/** - * @brief delete a peerDevice from local storage - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] peerDeviceId The device Id to be removed from local storage, shall be its GRUU - * - * Call is silently ignored if the device is not found in local storage - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_delete_peerDevice(lime_manager_t manager, const char *peerDeviceId); - -/** - * @brief Stale all sessions between localDeviceId and peerDevice. - * If peerDevice keep using this session to encrypt and we decrypt with success, the session will be reactivated - * but to encrypt a message to this peerDevice, a new session will be created. - * If no session is active between the given device, this call has no effect - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] localDeviceId Identify the local user account, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * @param[in] peerDeviceId The device Id of peer, shall be its GRUU - */ -int lime_ffi_stale_sessions(lime_manager_t manager, const char *localDeviceId, const char *peerDeviceId); -/** - * @brief Update: shall be called once a day at least, performs checks, updates and cleaning operations - * - * - check if we shall update a new SPk to X3DH server(SPk lifetime is set in settings) - * - check if we need to upload OPks to X3DH server - * - remove old SPks, clean double ratchet sessions (remove staled, clean their stored keys for skipped messages) - * - * Is performed for all users founds in local storage - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] localDeviceId Identify the local user account, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * @param[in] callback Performing encryption may involve the X3DH server and is thus asynchronous, when the operation is completed, - * this callback will be called giving the exit status and an error message in case of failure. - * @param[in] callbackUserData this pointer will be forwarded to the callback as first parameter - * @param[in] OPkServerLowLimit If server holds less OPk than this limit, generate and upload a batch of OPks - * @param[in] OPkBatchSize Number of OPks in a batch uploaded to server - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_update(lime_manager_t manager, const char *localDeviceId, const lime_ffi_Callback callback, void *callbackUserData, uint16_t OPkServerLowLimit, uint16_t OPkBatchSize); - -/** - * @brief Set the X3DH key server URL for this identified user - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] localDeviceId Identify the local user account, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * @param[in] x3dhServerUrl The complete url(including port) of the X3DH key server. It must connect using HTTPS. Example: https://sip5.linphone.org:25519 - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_set_x3dhServerUrl(lime_manager_t manager, const char *localDeviceId, const char *x3dhServerUrl); - -/** - * @brief Get the X3DH key server URL for this identified user - * - * @param[in] manager pointer to the opaque structure used to interact with lime - * @param[in] localDeviceId Identify the local user account, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU, in a NULL terminated string - * @param[in] x3dhServerUrl The complete url(including port) of the X3DH key server in a NULL terminated string - * @param[in,out] x3dhServerUrlSize Size of the previous buffer, is updated with actual size of data written(without the '\0', would give the same result as strlen.) - * - * @return LIME_FFI_SUCCESS or a negative error code - */ -int lime_ffi_get_x3dhServerUrl(lime_manager_t manager, const char *localDeviceId, char *x3dhServerUrl, size_t *x3dhServerUrlSize); - -#ifdef __cplusplus -} -#endif - -#endif /* lime__ffi_hpp */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 65e1727..ed2f4a8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -46,24 +46,15 @@ set(LIME_SOURCE_FILES_CXX lime_log.cpp ) -if (ENABLE_C_INTERFACE) - set(LIME_SOURCE_FILES_CXX ${LIME_SOURCE_FILES_CXX} lime_ffi.cpp) -endif() - -if (ENABLE_JNI) - set(LIME_SOURCE_FILES_CXX ${LIME_SOURCE_FILES_CXX} lime_jni.cpp) - add_subdirectory(java) -endif() - bc_apply_compile_flags(LIME_SOURCE_FILES_CXX STRICT_OPTIONS_CPP STRICT_OPTIONS_CXX) add_library(lime ${LIME_PRIVATE_HEADER_FILES} ${LIME_HEADER_FILES} ${LIME_SOURCE_FILES_CXX}) set_target_properties(lime PROPERTIES VERSION ${LIME_SO_VERSION}) -target_include_directories(lime PRIVATE ${JNI_INCLUDE_DIRS} INTERFACE +target_include_directories(lime PRIVATE INTERFACE $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> ) -target_link_libraries(lime PRIVATE ${BCToolbox_TARGET} ${Soci_TARGET} ${Soci_sqlite3_TARGET} ${JNI_LIBRARIES}) +target_link_libraries(lime PRIVATE ${BCToolbox_TARGET} ${Soci_TARGET} ${Soci_sqlite3_TARGET}) if(ENABLE_PQCRYPTO) target_link_libraries(lime PRIVATE ${PostQuantumCryptoEngine_TARGET}) endif() diff --git a/src/java/CMakeLists.txt b/src/java/CMakeLists.txt deleted file mode 100644 index 92061c5..0000000 --- a/src/java/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -############################################################################ -# CMakeLists.txt -# Copyright (C) 2019 Belledonne Communications, Grenoble France -# -############################################################################ -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -############################################################################ -find_package(Java REQUIRED) -include(UseJava) - -set (LIME_SOURCE_FILES_JAVA - org/linphone/lime/LimeException.java - org/linphone/lime/LimeCurveId.java - org/linphone/lime/LimeEncryptionPolicy.java - org/linphone/lime/LimeOutputBuffer.java - org/linphone/lime/LimePeerDeviceStatus.java - org/linphone/lime/LimeCallbackReturn.java - org/linphone/lime/LimeStatusCallback.java - org/linphone/lime/RecipientData.java - org/linphone/lime/LimePostToX3DH.java - org/linphone/lime/LimeManager.java -) - -add_jar(Lime ${LIME_SOURCE_FILES_JAVA}) - -get_target_property(Lime_jarFile Lime JAR_FILE) - -message(STATUS "Lime Jar file ${Lime_jarFile}") - diff --git a/src/java/org/linphone/lime/LimeCallbackReturn.java b/src/java/org/linphone/lime/LimeCallbackReturn.java deleted file mode 100644 index 8bd69aa..0000000 --- a/src/java/org/linphone/lime/LimeCallbackReturn.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - LimeCallbackReturn.java - @author Johan Pascal - @copyright Copyright (C) 2019 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -package org.linphone.lime; - -/** @brief Enumeration remapping the lime::CallbackReturn - * - java enumeration is mapped to an int - * - jni code map the same int to the original lime::CallbackReturn - */ -public enum LimeCallbackReturn { - SUCCESS(0), - FAIL(1); - - private int native_val; /* Store the native(used by jni) integer value */ - - private LimeCallbackReturn(int val) { - native_val = val; - } - - /** - * @brief static method to get an enum value from the native jni integer(used as returned value by native function) - * - * @param[in] val integer value mapped to the jni enum - * - * @return one of the enumeration value, unknown input will silently default to FAIL - */ - public static LimeCallbackReturn fromNative(int val) { - switch (val) { - case 0: - return LimeCallbackReturn.SUCCESS; - case 1: - default: - return LimeCallbackReturn.FAIL; - } - } - -} diff --git a/src/java/org/linphone/lime/LimeCurveId.java b/src/java/org/linphone/lime/LimeCurveId.java deleted file mode 100644 index 08e3881..0000000 --- a/src/java/org/linphone/lime/LimeCurveId.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - LimeCurveId.java - @author Johan Pascal - @copyright Copyright (C) 2019 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -package org.linphone.lime; - -public enum LimeCurveId { - C25519(1), /**< Curve 25519 */ - C448(2); /**< Curve 448-goldilocks */ - - private int native_val; /* Store the native(used by jni) integer value */ - - /** - * @brief get the native value (used to give input parameter values) - * @return the native value associated - */ - protected int getNative() {return native_val;} - - private LimeCurveId(int val) { - native_val = val; - } -} diff --git a/src/java/org/linphone/lime/LimeEncryptionPolicy.java b/src/java/org/linphone/lime/LimeEncryptionPolicy.java deleted file mode 100644 index b79eb2c..0000000 --- a/src/java/org/linphone/lime/LimeEncryptionPolicy.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - LimeEncryptionPolicy.java - @author Johan Pascal - @copyright Copyright (C) 2019 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -package org.linphone.lime; - -public enum LimeEncryptionPolicy { - DRMESSAGE(0), /**< the plaintext input is encrypted inside the Double Ratchet message (each recipient get a different encryption): not optimal for messages with numerous recipient */ - CIPHERMESSAGE(1), /**< the plaintext input is encrypted with a random key and this random key is encrypted to each participant inside the Double Ratchet message(for a single recipient the overhead is 48 bytes) */ - OPTIMIZEUPLOADSIZE(2), /**< optimize upload size: encrypt in DR message if plaintext is short enougth to beat the overhead introduced by cipher message scheme, otherwise use cipher message. Selection is made on upload size only. This is the default policy used */ - OPTIMIZEGLOBALBANDWIDTH(3); /**< optimize bandwith usage: encrypt in DR message if plaintext is short enougth to beat the overhead introduced by cipher message scheme, otherwise use cipher message. Selection is made on uploadand download (from server to recipients) sizes added. */ - - private int native_val; /* Store the native(used by jni) integer value */ - - /** - * @brief get the native value (used to give input parameter values) - * @return the native value associated - */ - protected int getNative() {return native_val;} - - private LimeEncryptionPolicy(int val) { - native_val = val; - } -} - diff --git a/src/java/org/linphone/lime/LimeException.java b/src/java/org/linphone/lime/LimeException.java deleted file mode 100644 index eb853fe..0000000 --- a/src/java/org/linphone/lime/LimeException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - LimeException.java - @author Johan Pascal - @copyright Copyright (C) 2019 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -package org.linphone.lime; - -public class LimeException extends Exception { - public LimeException(String message) { - super(message); - } -} diff --git a/src/java/org/linphone/lime/LimeManager.java b/src/java/org/linphone/lime/LimeManager.java deleted file mode 100644 index a37e1e1..0000000 --- a/src/java/org/linphone/lime/LimeManager.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - LimeManager.java - @author Johan Pascal - @copyright Copyright (C) 2019 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -package org.linphone.lime; - -/** - * @brief A java wrapper around the native Lime Manager interface - * - * To use this wrapper you must implement the interfaces - * - LimePostToX3DH to communicate with the X3DH Https server - * - LimeStatusCallback to manage the lime response to asynchronous operations: create/delete users, encrypt, update - */ -public class LimeManager { - private long nativePtr; // stores the native object pointer - - // Call the native constructor -> do it when the object is created - protected native void initialize(String db_access, LimePostToX3DH postObj); - - // Native functions involving enumerated paremeters not public - // Enumeration translation is done on java side - private native int n_decrypt(String localDeviceId, String recipientUserId, String senderDeviceId, byte[] DRmessage, byte[] cipherMessage, LimeOutputBuffer plainMessage); - private native void n_encrypt(String localDeviceId, String recipientUserId, RecipientData[] recipients, byte[] plainMessage, LimeOutputBuffer cipherMessage, LimeStatusCallback statusObj, int encryptionPolicy); - - private native void n_create_user(String localDeviceId, String serverURL, int curveId, int OPkInitialBatchSize, LimeStatusCallback statusObj); - private native void n_update(LimeStatusCallback statusObj, int OPkServerLowLimit, int OPkBatchSize); - - private native void n_set_peerDeviceStatus_Ik(String peerDeviceId, byte[] Ik, int status); - private native void n_set_peerDeviceStatus(String peerDeviceId, int status); - - private native int n_get_peerDeviceStatus(String peerDeviceId); - - - /** - * @brief Lime Manager constructor - * - * @param[in] db_access string used to access DB: can be filename for sqlite3 or access params for mysql, directly forwarded to SOCI session opening - * @param[in] postObj An object used to send data to the X3DH server - */ - public LimeManager(String db_access, LimePostToX3DH postObj) { - initialize(db_access, postObj); - } - - /** - * @brief Native ressource destructor - * We cannot rely on finalize (deprecated since java9), it must explicitely be called before the object is destroyed - * by the java environment - */ - public native void nativeDestructor(); - - /** - * @brief Create a user in local database and publish it on the given X3DH server - * - * The Lime user shall be created at the same time the account is created on the device, this function shall not be called again, attempt to re-create an already existing user will fail. - * A user is identified by its deviceId (shall be the GRUU) and must at creation select a base Elliptic curve to use, this setting cannot be changed later - * A user is published on an X3DH key server who must run using the same elliptic curve selected for this user (creation will fail otherwise), the server url cannot be changed later - * - * @param[in] localDeviceId Identify the local user acount to use, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * @param[in] serverURL The complete url(including port) of the X3DH key server. It must connect using HTTPS. Example: https://sip5.linphone.org:25519 - * @param[in] curveId Choice of elliptic curve to use as base for ECDH and EdDSA operation involved. Can be CurveId::c25519 or CurveId::c448. - * @param[in] OPkInitialBatchSize Number of OPks in the first batch uploaded to X3DH server - * @param[in] statusObj This operation contact the X3DH server and is thus asynchronous, when server responds, - * the statusObj.callback will be called giving the exit status and an error message in case of failure - * @note - * The OPkInitialBatchSize is optionnal, if not used, set to defaults 100 - */ - public void create_user(String localDeviceId, String serverURL, LimeCurveId curveId, int OPkInitialBatchSize, LimeStatusCallback statusObj) throws LimeException { - this.n_create_user(localDeviceId, serverURL, curveId.getNative(), OPkInitialBatchSize, statusObj); - } - /** - * @overload void create_user(String localDeviceId, String serverURL, LimeCurveId curveId, LimeStatusCallback statusObj) - */ - public void create_user(String localDeviceId, String serverURL, LimeCurveId curveId, LimeStatusCallback statusObj) throws LimeException { - this.n_create_user(localDeviceId, serverURL, curveId.getNative(), 100, statusObj); - } - - /** - * @brief Delete a user from local database and from the X3DH server - * - * if specified localDeviceId is not found in local Storage, throw an exception - * - * @param[in] localDeviceId Identify the local user acount to use, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * @param[in] statusObj This operation contact the X3DH server and is thus asynchronous, when server responds, - * the statusObj.callback will be called giving the exit status and an error message in case of failure - */ - public native void delete_user(String localDeviceId, LimeStatusCallback statusObj) throws LimeException; - - /** - * @brief Check if a user is present and active in local storage - * - * @param[in] localDeviceId Identify the local user acount to use, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * - * @return true if the user is active in the local storage, false otherwise - */ - public native boolean is_user(String localDeviceId) throws LimeException; - - /** - * @brief Encrypt a buffer (text or file) for a given list of recipient devices - * - * if specified localDeviceId is not found in local Storage, throw an exception - * - * Clarification on recipients: - * - * recipients information needed are a list of the device Id and one userId. The device Id shall be their GRUU while the userId is a sip:uri. - * - * recipient User Id is used to identify the actual intended recipient. Example: alice have two devices and is signed up on a conference having - * bob and claire as other members. The recipientUserId will be the conference sip:uri and device list will include: - * - alice other device - * - bob devices - * - claire devices - * If Alice write to Bob only, the recipientUserId will be bob sip:uri and recipient devices list : - * - alice other device - * - bob devices - * - * In all cases, the identified source of the message will be the localDeviceId - * - * If the X3DH server can't provide keys for a peer device, its status is set to fail and its DRmessage is empty. Other devices get their encrypted message - * If no peer device could get encrypted for all of them are missing keys on the X3DH server, the callback will be called with fail exit status - * - * @note nearly all parameters are shared pointers as the process being asynchronous, the ownership will be taken internally exempting caller to manage the buffers. - * - * @param[in] localDeviceId used to identify which local acount to use and also as the identified source of the message, shall be the GRUU - * @param[in] recipientUserId the Id of intended recipient, shall be a sip:uri of user or conference, is used as associated data to ensure no-one can mess with intended recipient - * @param[in,out] recipients a list of RecipientData holding: - * - the recipient device Id(GRUU) - * - an empty buffer to store the DRmessage which must then be routed to that recipient - * - the peer Status. If peerStatus is set to fail, this entry is ignored otherwise the peerStatus is set by the encrypt, see LimePeerDeviceStatus definition for details - * @param[in] plainMessage a buffer holding the message to encrypt, can be text or data. - * @param[out] cipherMessage points to the buffer to store the encrypted message which must be routed to all recipients(if one is produced, depends on encryption policy) - * @param[in] statusObj Performing encryption may involve the X3DH server and is thus asynchronous, when the operation is completed, - * this statusObj.callback will be called giving the exit status and an error message in case of failure. - * It is advised to store a reference to cipherMessage and recipients in this object so they can access - * the output of encryption as it won't be part of the callback parameters. - * @param[in] encryptionPolicy select how to manage the encryption: direct use of Double Ratchet message or encrypt in the cipher message and use the DR message to share the cipher message key - * default is optimized output size mode. - */ - public void encrypt(String localDeviceId, String recipientUserId, RecipientData[] recipients, byte[] plainMessage, LimeOutputBuffer cipherMessage, LimeStatusCallback statusObj, LimeEncryptionPolicy encryptionPolicy) { - this.n_encrypt(localDeviceId, recipientUserId, recipients, plainMessage, cipherMessage, statusObj, encryptionPolicy.getNative()); - } - /** - * @overload encrypt(String localDeviceId, String recipientUserId, RecipientData[] recipients, byte[] plainMessage, LimeOutputBuffer cipherMessage, LimeStatusCallback statusObj) - * convenience form using LimeEncryptionPolicy.OPTIMIZEUPLOADSIZE as default policy - */ - public void encrypt(String localDeviceId, String recipientUserId, RecipientData[] recipients, byte[] plainMessage, LimeOutputBuffer cipherMessage, LimeStatusCallback statusObj) { - this.n_encrypt(localDeviceId, recipientUserId, recipients, plainMessage, cipherMessage, statusObj, LimeEncryptionPolicy.OPTIMIZEUPLOADSIZE.getNative()); - } - - /** - * @brief Decrypt the given message - * - * if specified localDeviceId is not found in local Storage, throw an exception - * - * @param[in] localDeviceId used to identify which local acount to use and also as the recipient device ID of the message, shall be the GRUU - * @param[in] recipientUserId the Id of intended recipient, shall be a sip:uri of user or conference, is used as associated data to ensure no-one can mess with intended recipient - * it is not necessarily the sip:uri base of the GRUU as this could be a message from alice first device intended to bob being decrypted on alice second device - * @param[in] senderDeviceId Identify sender Device. This field shall be extracted from signaling data in transport protocol, is used to rebuild the authenticated data associated to the encrypted message - * @param[in] DRmessage Double Ratchet message targeted to current device - * @param[in] cipherMessage when present (depends on encryption policy) holds a common part of the encrypted message. Can be ignored or set to empty vector if not present in the incoming message. - * @param[out] plainMessage the output buffer - * - * @return LimePeerDeviceStatus.FAIL if we cannot decrypt the message, LimePeerDeviceStatus.UNKNOWN when it is the first message we ever receive from the sender device, LimePeerDeviceStatus.UNTRUSTED for known but untrusted sender device, or LimePeerDeviceStatus.TRUSTED if it is - */ - public LimePeerDeviceStatus decrypt(String localDeviceId, String recipientUserId, String senderDeviceId, byte[] DRmessage, byte[] cipherMessage, LimeOutputBuffer plainMessage) { - int native_status = this.n_decrypt(localDeviceId, recipientUserId, senderDeviceId, DRmessage, cipherMessage, plainMessage); - return LimePeerDeviceStatus.fromNative(native_status); - } - /** - * @overload decrypt(String localDeviceId, String recipientUserId, String senderDeviceId, byte[] DRmessage, LimeOutputBuffer plainMessage) - * convenience form to be called when no cipher message is received - */ - public LimePeerDeviceStatus decrypt(String localDeviceId, String recipientUserId, String senderDeviceId, byte[] DRmessage, LimeOutputBuffer plainMessage) { - // can't easily overload the native function and the native decrypt support empty cipherMessage buffer - byte[] dummyCipherMessage = new byte[0]; - int native_status = this.n_decrypt(localDeviceId, recipientUserId, senderDeviceId, DRmessage, dummyCipherMessage, plainMessage); - return LimePeerDeviceStatus.fromNative(native_status); - } - - /** - * @brief Update: shall be called once a day at least, performs checks, updates and cleaning operations - * - * - check if we shall update a new SPk to X3DH server(SPk lifetime is set in settings) - * - check if we need to upload OPks to X3DH server - * - remove old SPks, clean double ratchet sessions (remove staled, clean their stored keys for skipped messages) - * - * Is performed for all users founds in local storage - * - * @param[in] statusObj This operation may contact the X3DH server and is thus asynchronous, when server responds, - * this statusObj.callback will be called giving the exit status and an error message in case of failure. - * @param[in] OPkServerLowLimit If server holds less OPk than this limit, generate and upload a batch of OPks - * @param[in] OPkBatchSize Number of OPks in a batch uploaded to server - * - * @note - * The last two parameters are optional, if not used, set to defaults defined in lime::settings - * (not done with param default value as the lime::settings shall not be available in public include) - */ - public void update(LimeStatusCallback statusObj, int OPkServerLowLimit, int OPkBatchSize) { - this.n_update(statusObj, OPkServerLowLimit, OPkBatchSize); - } - /** - * @overload update(LimeStatusCallback statusObj) - * convenience form using default server limit(100) and batch size(25) - */ - public void update(LimeStatusCallback statusObj) { - this.n_update(statusObj, 100, 25); - } - - /** - * @brief retrieve self Identity Key, an EdDSA formatted public key - * - * if specified localDeviceId is not found in local Storage, throw an exception - * - * @param[in] localDeviceId used to identify which local account we're dealing with, shall be the GRUU - * @param[out] Ik the EdDSA public identity key, formatted as in RFC8032 - */ - public native void get_selfIdentityKey(String localDeviceId, LimeOutputBuffer Ik) throws LimeException; - - /** - * @brief set the peer device status flag in local storage: unsafe, trusted or untrusted. - * - * @param[in] peerDeviceId The device Id of peer, shall be its GRUU - * @param[in] Ik the EdDSA peer public identity key, formatted as in RFC8032 - * @param[in] status value of flag to set: accepted values are trusted, untrusted, unsafe - * - * throw an exception if given key doesn't match the one present in local storage - * if the status flag value is unexpected (not one of trusted, untrusted, unsafe), ignore the call - * if the status flag is unsafe or untrusted, ignore the value of Ik and call the version of this function without it - * - * if peer Device is not present in local storage and status is trusted or unsafe, it is added, if status is untrusted, it is just ignored - * - * General algorithm followed by the set_peerDeviceStatus functions - * - Status is valid? (not one of trusted, untrusted, unsafe)? No: return - * - status is trusted - * - We have Ik? -> No: return - * - Device is already in storage but Ik differs from the given one : exception - * - Insert/update in local storage - * - status is untrusted - * - Ik is ignored - * - Device already in storage? No: return - * - Device already in storage but current status is unsafe? Yes: return - * - update in local storage - * -status is unsafe - * - ignore Ik - * - insert/update the status. If inserted, insert an invalid Ik - */ - public void set_peerDeviceStatus(String peerDeviceId, byte[] Ik, LimePeerDeviceStatus status) throws LimeException{ - this.n_set_peerDeviceStatus_Ik(peerDeviceId, Ik, status.getNative()); - } - - /** - * @brief set the peer device status flag in local storage: unsafe or untrusted. - * - * This variation allows to set a peer Device status to unsafe or untrusted only whithout providing its identity key Ik - * - * @param[in] peerDeviceId The device Id of peer, shall be its GRUU - * @param[in] status value of flag to set: accepted values are untrusted or unsafe - * - * if the status flag value is unexpected (not one of untrusted, unsafe), ignore the call - * - * if peer Device is not present in local storage, it is inserted if status is unsafe and call is ignored if status is untrusted - * if the status is untrusted but the current status in local storage is unsafe, ignore the call - * Any call to the other form of the function with a status to unsafe or untrusted is rerouted to this function - */ - public void set_peerDeviceStatus(String peerDeviceId, LimePeerDeviceStatus status) { - this.n_set_peerDeviceStatus(peerDeviceId, status.getNative()); - } - - /** - * @brief get the status of a peer device: unknown, untrusted, trusted, unsafe - * - * @param[in] peerDeviceId The device Id of peer, shall be its GRUU - * - * @return unknown if the device is not in localStorage, untrusted, trusted or unsafe according to the stored value of peer device status flag otherwise - */ - public LimePeerDeviceStatus get_peerDeviceStatus(String peerDeviceId) { - return LimePeerDeviceStatus.fromNative(this.n_get_peerDeviceStatus(peerDeviceId)); - } - - /** - * @brief delete a peerDevice from local storage - * - * @param[in] peerDeviceId The device Id to be removed from local storage, shall be its GRUU - * - * Call is silently ignored if the device is not found in local storage - */ - public native void delete_peerDevice(String peerDeviceId); - - /** - * @brief Set the X3DH key server URL for this identified user - * if specified localDeviceId is not found in local Storage, throw an exception - * - * @param[in] localDeviceId Identify the local user acount to use, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * @param[in] serverURL The complete url(including port) of the X3DH key server. It must connect using HTTPS. Example: https://sip5.linphone.org:25519 - */ - public native void set_x3dhServerUrl(String localDeviceId, String serverURL) throws LimeException; - - /** - * @brief Stale all sessions between localDeviceId and peerDevice. - * If peerDevice keep using this session to encrypt and we decrypt with success, the session will be reactivated - * but to encrypt a message to this peerDevice, a new session will be created. - * If no session is active between the given device, this call has no effect - * - * @param[in] localDeviceId Identify the local user account, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * @param[in] peerDeviceId The device Id of peer, shall be its GRUU - */ - public native void stale_sessions(String localDeviceId, String peerDeviceId) throws LimeException; - - - /** - * @brief Get the X3DH key server URL for this identified user - * if specified localDeviceId is not found in local Storage, throw an exception - * - * @param[in] localDeviceId Identify the local user acount to use, it must be unique and is also be used as Id on the X3DH key server, it shall be the GRUU - * - * @return serverURL The complete url(including port) of the X3DH key server. - */ - public native String get_x3dhServerUrl(String localDeviceId) throws LimeException; - - /** - * @brief native function to process the X3DH server response - * - * This function must be called by the response handler to forward the response (and http answer code) - * - * @param[in] ptr a native object pointer passed to the postToX3DH method - * @param[in] responseCode the HTTP server response code - * @param[in] response the binary X3DH server response - * - */ - public static native void process_X3DHresponse(long ptr, int responseCode, byte[] response); -} diff --git a/src/java/org/linphone/lime/LimeOutputBuffer.java b/src/java/org/linphone/lime/LimeOutputBuffer.java deleted file mode 100644 index ba00d51..0000000 --- a/src/java/org/linphone/lime/LimeOutputBuffer.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - LimeOutputBuffer.java - @author Johan Pascal - @copyright Copyright (C) 2019 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -package org.linphone.lime; - -/* encapsulate a byte buffer so this object is instanciated in java and passed as output parameter to the native function - * but the encapsulated byte buffer is created and populated by the native function */ -public class LimeOutputBuffer { - public byte[] buffer; -} - diff --git a/src/java/org/linphone/lime/LimePeerDeviceStatus.java b/src/java/org/linphone/lime/LimePeerDeviceStatus.java deleted file mode 100644 index d340512..0000000 --- a/src/java/org/linphone/lime/LimePeerDeviceStatus.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - LimePeerDeviceStatus.java - @author Johan Pascal - @copyright Copyright (C) 2019 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -package org.linphone.lime; - -/** @brief Enumeration remapping the lime::PeerDeviceStatus - * - java enumeration is mapped to an int - * - jni code map the same int to the original lime::PeerDeviceStatus - */ -public enum LimePeerDeviceStatus { - UNTRUSTED(0), /**< we know this device but do not trust it, that information shall be displayed to the end user, a colour code shall be enough */ - TRUSTED(1), /**< this peer device already got its public identity key validated, that information shall be displayed to the end user too */ - UNSAFE(2), /**< this status is a helper for the library user. It is used only by the peerDeviceStatus accessor functions */ - FAIL(3), /**< when returned by decrypt : we could not decrypt the incoming message\n - when returned by encrypt in the peerStatus: we could not encrypt to this recipient(probably because it does not published keys on the X3DH server) */ - UNKNOWN(4); /**< when returned after encryption or decryption, means it is the first time we communicate with this device (and thus create a DR session with it)\n - when returned by a get_peerDeviceStatus: this device is not in localStorage */ - - - private int native_val; /* Store the native(used by jni) integer value */ - - /** - * @brief get the native value (used to give input parameter values) - * @return the native value associated - */ - protected int getNative() {return native_val;} - - /** - * @brief static method to get an enum value from the native jni integer(used as returned value by native function) - * - * @param[in] val integer value mapped to the jni enum - * - * @return one of the enumeration value, unknown input will silently default to UNKNOWN - */ - protected static LimePeerDeviceStatus fromNative(int val) { - switch (val) { - case 0: - return LimePeerDeviceStatus.UNTRUSTED; - case 1: - return LimePeerDeviceStatus.TRUSTED; - case 2: - return LimePeerDeviceStatus.UNSAFE; - case 3: - return LimePeerDeviceStatus.FAIL; - case 4: - default: - return LimePeerDeviceStatus.UNKNOWN; - } - } - - LimePeerDeviceStatus(int val) { - native_val = val; - } -} diff --git a/src/java/org/linphone/lime/LimePostToX3DH.java b/src/java/org/linphone/lime/LimePostToX3DH.java deleted file mode 100644 index cd00df3..0000000 --- a/src/java/org/linphone/lime/LimePostToX3DH.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - LimePostToX3DH.java - @author Johan Pascal - @copyright Copyright (C) 2019 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -package org.linphone.lime; - -/** @brief Define an interface to communicate with the X3DH server - */ -public interface LimePostToX3DH { - /** - * @brief Function called by native code to post a message to the X3DH server - * - * @param[in] ptr a native object pointer (stored in java long), must be returned along the server response to process it - * @param[in] url the X3DH server's URL - * @param[in] from shall be included in the from field of HTTPS packet sent to the server(holds the local device Id of message sender) - * @param[in] message the binary content of the message to be sent - * - * @note: To forward the server's response, call the LimeManager.process_response static method giving back the native object pointer - */ - public void postToX3DHServer(long ptr, String url, String from, byte[] message); -} diff --git a/src/java/org/linphone/lime/LimeStatusCallback.java b/src/java/org/linphone/lime/LimeStatusCallback.java deleted file mode 100644 index 3581f71..0000000 --- a/src/java/org/linphone/lime/LimeStatusCallback.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - LimeStatusCallback.java - @author Johan Pascal - @copyright Copyright (C) 2019 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -package org.linphone.lime; - -/** @brief Define an interface for the status callback - * The native code will call this callback function on - * the LimeStatusCallback object passed as parameter to it. - */ -public interface LimeStatusCallback { - /** - * @brief Function called by native code when asynchronous processing is completed - * - * @param[in] status an integer mapped lime:CallbackReturn, use LimeCallbackReturn.fromNative to turn it into a java enumeration, do not use it directly - * @param[in] message a string message giving some details in case of failure - */ - public void callback(int status, String message); -} diff --git a/src/java/org/linphone/lime/RecipientData.java b/src/java/org/linphone/lime/RecipientData.java deleted file mode 100644 index 3c8b23c..0000000 --- a/src/java/org/linphone/lime/RecipientData.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - RecipientData.java - @author Johan Pascal - @copyright Copyright (C) 2019 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -package org.linphone.lime; - -/** @brief The encrypt function input/output data structure - * - * give a recipient GRUU and get it back with the header which must be sent to recipient with the cipher text - */ -public class RecipientData { - public String deviceId; /**< The recipient device id(shall be its GRUU)*/ - private int peerStatus; /**< peer Status is stored in native enumeration, so native code can access it easily, it is thus access through methods translating to LimePeerDeviceStatus java enum\n - input: if set to FAIL, this entry will be ignored by the encrypt function\n - output: after encrypt calls back, it will hold the status of this peer device:\n - - UNKNOWN: first interaction with this device) - - UNTRUSTED: device is kown but we never confirmed its identity public key - - TRUSTED: we already confirmed this device identity public key - - FAIL: we could not encrypt for this device, probably because it never published its keys on the X3DH server */ - public byte[] DRmessage; /**< after encrypt calls back, it will hold the Double Ratchet message targeted to the specified recipient. */ - - public LimePeerDeviceStatus getPeerStatus() { - return LimePeerDeviceStatus.fromNative(peerStatus); - } - - public void setPeerStatus(LimePeerDeviceStatus status) { - peerStatus = status.getNative(); - } - - public RecipientData(String p_deviceId) { - deviceId = p_deviceId; - peerStatus = LimePeerDeviceStatus.UNKNOWN.getNative(); // default to unknown - } - - public RecipientData(String p_deviceId, LimePeerDeviceStatus status) { - deviceId = p_deviceId; - peerStatus = status.getNative(); - } -} diff --git a/src/jni/LICENSE.txt b/src/jni/LICENSE.txt deleted file mode 100644 index 7e3bdd6..0000000 --- a/src/jni/LICENSE.txt +++ /dev/null @@ -1,13 +0,0 @@ -Copyright © 2016, Mapbox - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. diff --git a/src/jni/advanced_ownership.hpp b/src/jni/advanced_ownership.hpp deleted file mode 100644 index aada43f..0000000 --- a/src/jni/advanced_ownership.hpp +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once - -#include <jni/functions.hpp> - -namespace jni - { - // A deleter that gets the JNIEnv via GetEnv, rather than storing the value passed to the constructor. - // The deleting thread must have a JVM attachment. - // - // Useful when deletion will happen on an auxiliary thread, particularly the finalizer thread. In such - // cases, you may use one of the following: - // - // low-level: UniqueGlobalRef<jobject, EnvGettingDeleter> and NewGlobalRef<EnvGettingDeleter> - // high-level: Global<Object<Tag>, EnvGettingDeleter> and obj.NewGlobalRef<EnvGettingDeleter> - // - template < RefDeletionMethod DeleteRef > - class EnvGettingDeleter - { - private: - JavaVM* vm = nullptr; - - public: - EnvGettingDeleter() = default; - EnvGettingDeleter(JNIEnv& e) : vm(&GetJavaVM(e)) {} - - void operator()(jobject* p) const - { - if (p) - { - assert(vm); - (GetEnv(*vm).*DeleteRef)(Unwrap(p)); - } - } - }; - - // A deleter that first tries GetEnv, but falls back to AttachCurrentThread if a JVM is not already attached. - // In the latter case, it detaches after deleting the reference. - // - // Useful when deletion will happen on an auxiliary thread which may or may not have a JVM attachment. In such - // cases, you may use one of the following: - // - // low-level: UniqueGlobalRef<jobject, EnvAttachingDeleter> and NewGlobalRef<EnvAttachingDeleter> - // high-level: Global<Object<Tag>, EnvAttachingDeleter> and obj.NewGlobalRef<EnvAttachingDeleter> - // - template < RefDeletionMethod DeleteRef > - class EnvAttachingDeleter - { - private: - JavaVM* vm = nullptr; - - public: - EnvAttachingDeleter() = default; - EnvAttachingDeleter(JNIEnv& e) : vm(&GetJavaVM(e)) {} - - void operator()(jobject* p) const - { - if (p) - { - assert(vm); - JNIEnv* env = nullptr; - jint err = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_1); - if (err == JNI_OK) - { - (env->*DeleteRef)(Unwrap(p)); - } - else if (err == JNI_EDETACHED) - { - ((*AttachCurrentThread(*vm)).*DeleteRef)(Unwrap(p)); - } - else - { - CheckErrorCode(err); - } - } - } - }; - - // A deleter that tries to get the JNIEnv via GetEnv, and does nothing if that fails. - // - // This is used to ignore GlobalRef deletions that happen after a thread has been detached, - // for instance during process shutdown, when there's no need to release the reference anyway. - // Specifically, it's what Class<T>::Singleton uses. - // - template < RefDeletionMethod DeleteRef > - class EnvIgnoringDeleter - { - private: - JavaVM* vm = nullptr; - - public: - EnvIgnoringDeleter() = default; - EnvIgnoringDeleter(JNIEnv& e) : vm(&GetJavaVM(e)) {} - - void operator()(jobject* p) const - { - if (p) - { - assert(vm); - JNIEnv* env = nullptr; - jint err = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_1); - if (err == JNI_OK) - { - (env->*DeleteRef)(Unwrap(p)); - } - else if (err != JNI_EDETACHED) - { - CheckErrorCode(err); - } - } - } - }; - } diff --git a/src/jni/array.hpp b/src/jni/array.hpp deleted file mode 100644 index 9c3338d..0000000 --- a/src/jni/array.hpp +++ /dev/null @@ -1,147 +0,0 @@ -#pragma once - -#include <jni/functions.hpp> -#include <jni/object.hpp> -#include <jni/tagging.hpp> -#include <jni/make.hpp> - -namespace jni - { - template < class E, class Enable > - class Array; - - template < class E > - class Array< E, std::enable_if_t<IsPrimitive<E>::value> > : public Object< ArrayTag<E> > - { - public: - using SuperType = Object< ArrayTag<E> >; - using UntaggedType = typename SuperType::UntaggedType; - using ElementType = E; - - protected: - explicit Array(std::nullptr_t = nullptr) - {} - - explicit Array(UntaggedType* p) - : SuperType(p) - {} - - Array(const Array&) = delete; - Array& operator=(const Array&) = delete; - - public: - jsize Length(JNIEnv& env) const - { - return GetArrayLength(env, SafeDereference(env, this->get())); - } - - ElementType Get(JNIEnv& env, jsize index) const - { - ElementType e; - GetArrayRegion(env, SafeDereference(env, this->get()), index, 1, &e); - return e; - } - - void Set(JNIEnv& env, jsize index, const ElementType& value) - { - SetArrayRegion(env, SafeDereference(env, this->get()), index, 1, &value); - } - - template < class Array > - void GetRegion(JNIEnv& env, jsize start, Array& buf) const - { - GetArrayRegion(env, SafeDereference(env, this->get()), start, buf); - } - - template < class Array > - void SetRegion(JNIEnv& env, jsize start, const Array& buf) - { - SetArrayRegion(env, SafeDereference(env, this->get()), start, buf); - } - - static Local<Array<E>> New(JNIEnv& env, jsize length) - { - return Local<Array<E>>(env, &NewArray<E>(env, length)); - } - }; - - template < class TheTag > - class Array< Object<TheTag> > : public Object< ArrayTag<Object<TheTag>> > - { - public: - using SuperType = Object< ArrayTag<Object<TheTag>> >; - using UntaggedType = typename SuperType::UntaggedType; - using TagType = TheTag; - using ElementType = Object<TagType>; - using UntaggedElementType = typename ElementType::UntaggedType; - - protected: - explicit Array(std::nullptr_t = nullptr) - {} - - explicit Array(UntaggedType* p) - : SuperType(p) - {} - - Array(const Array&) = delete; - Array& operator=(const Array&) = delete; - - public: - jsize Length(JNIEnv& env) const - { - return GetArrayLength(env, SafeDereference(env, this->get())); - } - - Local<ElementType> Get(JNIEnv& env, jsize index) const - { - return Local<ElementType>(env, - reinterpret_cast<UntaggedElementType*>( - GetObjectArrayElement(env, SafeDereference(env, this->get()), index))); - } - - void Set(JNIEnv& env, jsize index, const ElementType& value) - { - SetObjectArrayElement(env, SafeDereference(env, this->get()), index, Untag(value)); - } - - static Local<Array<Object<TheTag>>> New(JNIEnv& env, jsize length, const Object<TheTag>* initialElement = nullptr) - { - return Local<Array<Object<TheTag>>>(env, &NewObjectArray(env, length, *Class<TheTag>::Singleton(env), initialElement ? initialElement->get() : nullptr)); - } - }; - - template < class T > - std::vector<T> MakeAnything(ThingToMake<std::vector<T>>, JNIEnv& env, const Array<T>& array) - { - NullCheck(env, array.get()); - std::vector<T> result(GetArrayLength(env, *array)); - GetArrayRegion(env, *array, 0, result); - return result; - } - - template < class T > - Local<Array<T>> MakeAnything(ThingToMake<Array<T>>, JNIEnv& env, const std::vector<T>& array) - { - Local<Array<T>> result = Local<Array<T>>(env, &NewArray<T>(env, array.size())); - SetArrayRegion(env, *result, 0, array); - return result; - } - - inline - std::string MakeAnything(ThingToMake<std::string>, JNIEnv& env, const Array<jbyte>& array) - { - NullCheck(env, array.get()); - std::string result; - result.resize(GetArrayLength(env, *array)); - GetArrayRegion(env, *array, 0, result.size(), reinterpret_cast<jbyte*>(&result[0])); - return result; - } - - inline - Local<Array<jbyte>> MakeAnything(ThingToMake<Array<jbyte>>, JNIEnv& env, const std::string& string) - { - Local<Array<jbyte>> result(env, &NewArray<jbyte>(env, string.size())); - SetArrayRegion(env, *result, 0, string.size(), reinterpret_cast<const jbyte*>(&string[0])); - return result; - } - } diff --git a/src/jni/arraylike.hpp b/src/jni/arraylike.hpp deleted file mode 100644 index d605f84..0000000 --- a/src/jni/arraylike.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include <type_traits> -#include <string> -#include <array> -#include <vector> - -namespace jni - { - template < class T > struct IsArraylike: std::false_type {}; - - template < class E, std::size_t n > struct IsArraylike< E[n] > : std::true_type {}; - template < class E, std::size_t n > struct IsArraylike< std::array<E,n> > : std::true_type {}; - template < class E, class A > struct IsArraylike< std::vector<E,A> > : std::true_type {}; - template < class C, class T, class A > struct IsArraylike< std::basic_string<C,T,A> > : std::true_type {}; - - - template < class T > struct ArraylikeElementType; - - template < class E, std::size_t n > struct ArraylikeElementType< E[n] > { using Type = E; }; - template < class E, std::size_t n > struct ArraylikeElementType< std::array<E,n> > { using Type = E; }; - template < class E, class A > struct ArraylikeElementType< std::vector<E,A> > { using Type = E; }; - template < class C, class T, class A > struct ArraylikeElementType< std::basic_string<C,T,A> > { using Type = C; }; - - template < class T > using ArraylikeElement = typename ArraylikeElementType<T>::type; - - - template < class E, std::size_t n > E * ArraylikeData(E(&a)[n]) { return a; } - template < class E, std::size_t n > E * ArraylikeData( std::array<E,n>& a) { return a.data(); } - template < class E, std::size_t n > E const * ArraylikeData(const std::array<E,n>& a) { return a.data(); } - template < class E, class A > E * ArraylikeData( std::vector<E,A>& a) { return a.data(); } - template < class E, class A > E const * ArraylikeData(const std::vector<E,A>& a) { return a.data(); } - template < class C, class T, class A > C * ArraylikeData( std::basic_string<C,T,A>& a) { return &a[0]; } - template < class C, class T, class A > C const * ArraylikeData(const std::basic_string<C,T,A>& a) { return &a[0]; } - - - template < class E, std::size_t n > std::size_t ArraylikeSize(E(&)[n]) { return n; } - template < class E, std::size_t n > std::size_t ArraylikeSize(const std::array<E,n>&) { return n; } - template < class E, class A > std::size_t ArraylikeSize(const std::vector<E,A>& a) { return a.size(); } - template < class C, class T, class A > std::size_t ArraylikeSize(const std::basic_string<C,T,A>& a) { return a.size(); } - } diff --git a/src/jni/boxing.hpp b/src/jni/boxing.hpp deleted file mode 100644 index 5660361..0000000 --- a/src/jni/boxing.hpp +++ /dev/null @@ -1,159 +0,0 @@ -#pragma once - -#include <jni/class.hpp> -#include <jni/object.hpp> - -namespace jni - { - template < class > struct Boxer; - template < class > struct Unboxer; - - template < class Unboxed > - decltype(auto) Box(JNIEnv& env, Unboxed&& unboxed) - { - return Boxer<typename std::decay<Unboxed>::type>().Box(env, std::forward<Unboxed>(unboxed)); - } - - template < class T > - decltype(auto) Unbox(JNIEnv& env, const T& boxed) - { - return Unboxer<typename T::TagType>().Unbox(env, boxed); - } - - - struct BooleanTag - { - using SuperTag = ObjectTag; - static constexpr auto Name() { return "java/lang/Boolean"; } - static constexpr auto BoxStaticMethodName() { return "valueOf"; } - static constexpr auto UnboxMethodName() { return "booleanValue"; } - }; - - struct CharacterTag - { - using SuperTag = ObjectTag; - static constexpr auto Name() { return "java/lang/Character"; } - static constexpr auto BoxStaticMethodName() { return "valueOf"; } - static constexpr auto UnboxMethodName() { return "charValue"; } - }; - - struct NumberTag - { - using SuperTag = ObjectTag; - static constexpr auto Name() { return "java/lang/Number"; } - }; - - struct ByteTag - { - using SuperTag = NumberTag; - static constexpr auto Name() { return "java/lang/Byte"; } - static constexpr auto BoxStaticMethodName() { return "valueOf"; } - static constexpr auto UnboxMethodName() { return "byteValue"; } - }; - - struct ShortTag - { - using SuperTag = NumberTag; - static constexpr auto Name() { return "java/lang/Short"; } - static constexpr auto BoxStaticMethodName() { return "valueOf"; } - static constexpr auto UnboxMethodName() { return "shortValue"; } - }; - - struct IntegerTag - { - using SuperTag = NumberTag; - static constexpr auto Name() { return "java/lang/Integer"; } - static constexpr auto BoxStaticMethodName() { return "valueOf"; } - static constexpr auto UnboxMethodName() { return "intValue"; } - }; - - struct LongTag - { - using SuperTag = NumberTag; - static constexpr auto Name() { return "java/lang/Long"; } - static constexpr auto BoxStaticMethodName() { return "valueOf"; } - static constexpr auto UnboxMethodName() { return "longValue"; } - }; - - struct FloatTag - { - using SuperTag = NumberTag; - static constexpr auto Name() { return "java/lang/Float"; } - static constexpr auto BoxStaticMethodName() { return "valueOf"; } - static constexpr auto UnboxMethodName() { return "floatValue"; } - }; - - struct DoubleTag - { - using SuperTag = NumberTag; - static constexpr auto Name() { return "java/lang/Double"; } - static constexpr auto BoxStaticMethodName() { return "valueOf"; } - static constexpr auto UnboxMethodName() { return "doubleValue"; } - }; - - - using Boolean = Object<BooleanTag>; - using Character = Object<CharacterTag>; - using Number = Object<NumberTag>; - using Byte = Object<ByteTag>; - using Short = Object<ShortTag>; - using Integer = Object<IntegerTag>; - using Long = Object<LongTag>; - using Float = Object<FloatTag>; - using Double = Object<DoubleTag>; - - - template < class Tag, class Unboxed > - struct PrimitiveTypeBoxer - { - Local<Object<Tag>> Box(JNIEnv& env, Unboxed unboxed) const - { - static auto& klass = Class<Tag>::Singleton(env); - static auto box = klass.template GetStaticMethod<Object<Tag> (Unboxed)>(env, Tag::BoxStaticMethodName()); - return klass.Call(env, box, unboxed); - } - }; - - template <> struct Boxer< jboolean > : PrimitiveTypeBoxer< BooleanTag , jboolean > {}; - template <> struct Boxer< jbyte > : PrimitiveTypeBoxer< ByteTag , jbyte > {}; - template <> struct Boxer< jchar > : PrimitiveTypeBoxer< CharacterTag , jchar > {}; - template <> struct Boxer< jshort > : PrimitiveTypeBoxer< ShortTag , jshort > {}; - template <> struct Boxer< jint > : PrimitiveTypeBoxer< IntegerTag , jint > {}; - template <> struct Boxer< jlong > : PrimitiveTypeBoxer< LongTag , jlong > {}; - template <> struct Boxer< jfloat > : PrimitiveTypeBoxer< FloatTag , jfloat > {}; - template <> struct Boxer< jdouble > : PrimitiveTypeBoxer< DoubleTag , jdouble > {}; - - - template < class Tag, class Unboxed > - struct PrimitiveTypeUnboxer - { - Unboxed Unbox(JNIEnv& env, const Object<Tag>& boxed) const - { - static auto& klass = Class<Tag>::Singleton(env); - static auto unbox = klass.template GetMethod<Unboxed ()>(env, Tag::UnboxMethodName()); - return boxed.Call(env, unbox); - } - }; - - template <> struct Unboxer< BooleanTag > : PrimitiveTypeUnboxer< BooleanTag , jboolean > {}; - template <> struct Unboxer< ByteTag > : PrimitiveTypeUnboxer< ByteTag , jbyte > {}; - template <> struct Unboxer< CharacterTag > : PrimitiveTypeUnboxer< CharacterTag , jchar > {}; - template <> struct Unboxer< ShortTag > : PrimitiveTypeUnboxer< ShortTag , jshort > {}; - template <> struct Unboxer< IntegerTag > : PrimitiveTypeUnboxer< IntegerTag , jint > {}; - template <> struct Unboxer< LongTag > : PrimitiveTypeUnboxer< LongTag , jlong > {}; - template <> struct Unboxer< FloatTag > : PrimitiveTypeUnboxer< FloatTag , jfloat > {}; - template <> struct Unboxer< DoubleTag > : PrimitiveTypeUnboxer< DoubleTag , jdouble > {}; - - - template < class Tag > - struct Boxer<jni::Object<Tag>> - { - const Object<Tag>& Box(JNIEnv&, const jni::Object<Tag>& o) const { return o; } - }; - - template < class Tag > - struct Unboxer - { - const Object<Tag>& Unbox(JNIEnv&, const jni::Object<Tag>& o) const { return o; } - }; - } diff --git a/src/jni/class.hpp b/src/jni/class.hpp deleted file mode 100644 index 6cf96c2..0000000 --- a/src/jni/class.hpp +++ /dev/null @@ -1,137 +0,0 @@ -#pragma once - -#include <jni/functions.hpp> -#include <jni/tagging.hpp> -#include <jni/advanced_ownership.hpp> -#include <jni/object.hpp> - -namespace jni - { - template < class TheTag, class... > class Constructor; - template < class TheTag, class > class Field; - template < class TheTag, class > class StaticField; - template < class TheTag, class > class Method; - template < class TheTag, class > class StaticMethod; - - template < class TheTag > - class Class : public Object<ClassTag> - { - public: - using TagType = TheTag; - using SuperType = Object<ClassTag>; - using UntaggedType = jclass; - - protected: - explicit Class(std::nullptr_t = nullptr) - {} - - explicit Class(UntaggedType* p) - : SuperType(p) - {} - - Class(const Class&) = delete; - Class& operator=(const Class&) = delete; - - public: - template < class... ExpectedArgs, class... ActualArgs > - auto New(JNIEnv& env, const Constructor<TagType, ExpectedArgs...>& method, const ActualArgs&... args) const - -> std::enable_if_t< Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, Local<Object<TagType>> > - { - return Local<Object<TagType>>(env, &NewObject(env, *this->get(), method, Untag(args)...)); - } - - template < class T > - auto Get(JNIEnv& env, const StaticField<TagType, T>& field) const - -> std::enable_if_t< IsPrimitive<T>::value, T > - { - return jni::GetStaticField<T>(env, *this->get(), field); - } - - template < class T > - auto Get(JNIEnv& env, const StaticField<TagType, T>& field) const - -> std::enable_if_t< !IsPrimitive<T>::value, Local<T> > - { - return Local<T>(env, reinterpret_cast<typename T::UntaggedType*>(jni::GetStaticField<jobject*>(env, *this->get(), field))); - } - - template < class T > - auto Set(JNIEnv& env, const StaticField<TagType, T>& field, T value) const - -> std::enable_if_t< IsPrimitive<T>::value > - { - SetStaticField<T>(env, *this->get(), field, value); - } - - template < class Expected, class Actual > - auto Set(JNIEnv& env, const StaticField<TagType, Expected>& field, const Actual& value) const - -> std::enable_if_t< !IsPrimitive<Expected>::value - && std::is_convertible<const Actual&, const Expected&>::value > - { - SetStaticField<jobject*>(env, *this->get(), field, value.get()); - } - - template < class R, class... ExpectedArgs, class... ActualArgs > - auto Call(JNIEnv& env, const StaticMethod<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const - -> std::enable_if_t< IsPrimitive<R>::value - && Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, R > - { - return CallStaticMethod<R>(env, *this->get(), method, Untag(args)...); - } - - template < class R, class... ExpectedArgs, class... ActualArgs > - auto Call(JNIEnv& env, const StaticMethod<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const - -> std::enable_if_t< !IsPrimitive<R>::value - && !std::is_void<R>::value - && Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, Local<R> > - { - return Local<R>(env, reinterpret_cast<typename R::UntaggedType*>(CallStaticMethod<jobject*>(env, *this->get(), method, Untag(args)...))); - } - - template < class... ExpectedArgs, class... ActualArgs > - auto Call(JNIEnv& env, const StaticMethod<TagType, void (ExpectedArgs...)>& method, const ActualArgs&... args) const - -> std::enable_if_t< Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value > - { - CallStaticMethod<void>(env, *this->get(), method, Untag(args)...); - } - - static Local<Class> Find(JNIEnv& env) - { - return Local<Class>(env, &FindClass(env, TagType::Name())); - } - - static const Class& Singleton(JNIEnv& env) - { - static Global<Class, EnvIgnoringDeleter> singleton = NewGlobal<EnvIgnoringDeleter>(env, Find(env)); - return singleton; - } - - template < class... Args > - Constructor<TagType, Args...> GetConstructor(JNIEnv& env) const - { - return Constructor<TagType, Args...>(env, *this); - } - - template < class T > - Field<TagType, T> GetField(JNIEnv& env, const char* name) const - { - return Field<TagType, T>(env, *this, name); - } - - template < class T > - StaticField<TagType, T> GetStaticField(JNIEnv& env, const char* name) const - { - return StaticField<TagType, T>(env, *this, name); - } - - template < class T > - Method<TagType, T> GetMethod(JNIEnv& env, const char* name) const - { - return Method<TagType, T>(env, *this, name); - } - - template < class T > - StaticMethod<TagType, T> GetStaticMethod(JNIEnv& env, const char* name) const - { - return StaticMethod<TagType, T>(env, *this, name); - } - }; - } diff --git a/src/jni/constructor.hpp b/src/jni/constructor.hpp deleted file mode 100644 index 97896c9..0000000 --- a/src/jni/constructor.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include <jni/method.hpp> - -namespace jni - { - template < class TagType, class... Args > - class Constructor : public Method<TagType, void (Args...)> - { - public: - Constructor(JNIEnv& env, const Class<TagType>& clazz) - : Method<TagType, void (Args...)>(env, clazz, "<init>") - {} - }; - } diff --git a/src/jni/errors.hpp b/src/jni/errors.hpp deleted file mode 100644 index 7e0ce52..0000000 --- a/src/jni/errors.hpp +++ /dev/null @@ -1,119 +0,0 @@ -#pragma once - -#include <jni/types.hpp> -#include <jni/traits.hpp> - -#include <system_error> -#include <string> - -namespace std - { - template <> struct is_error_code_enum<jni::error> : public true_type {}; - } - -namespace jni - { - inline const std::error_category& ErrorCategory() - { - class Impl : public std::error_category - { - public: - const char* name() const noexcept override - { - return "JNI"; - } - - std::string message(int ev) const override - { - switch (static_cast<error>(ev)) - { - case jni_ok: return "OK"; - case jni_err: return "Unspecified error"; - case jni_edetached: return "Detached error"; - case jni_eversion: return "Version error"; - } - return "Unknown error"; - } - }; - - static Impl impl; - return impl; - } - - inline void CheckErrorCode(jint err) - { - if (err != JNI_OK) throw std::system_error(err, ErrorCategory()); - } - - - // An exception class indicating the presence of a pending Java exception. - // Note that it does not extract the message or other information from the - // Java exception; it's not possible to do so without clearing the pending - // Java exception, and the calling code needs the option not to do that. - // In most cases, the desired behavior is that the thrown PendingJavaException - // is caught by an exception handler just before returning to JVM control, and - // discarded there. Upon returning to JVM control, Java exception handling - // will take over, processing the still-pending Java exception. - - class PendingJavaException {}; - - template < class R > - R CheckJavaException(JNIEnv& env, R&& r) - { - if (env.ExceptionCheck()) throw PendingJavaException(); - return std::move(r); - } - - inline void CheckJavaException(JNIEnv& env) - { - if (env.ExceptionCheck()) throw PendingJavaException(); - } - - inline void CheckJavaExceptionThenErrorCode(JNIEnv& env, jint err) - { - CheckJavaException(env); - CheckErrorCode(err); - } - - - inline ::jclass JavaErrorClass(JNIEnv& env) - { - return env.FindClass("java/lang/Error"); - } - - // A function to be called from within a try / catch wrapper for a native method: - // - // void nativeMethod(JNIEnv* env, ...) - // { - // try - // { - // ... - // } - // catch (...) - // { - // jni::ThrowJavaError(*env, std::current_exception()); - // } - // } - // - // `PendingJavaException` is caught and ignored, other exceptions are converted to - // a pending Java exception of class `java.lang.Error`. - - inline void ThrowJavaError(JNIEnv& env, std::exception_ptr e) - { - try - { - std::rethrow_exception(e); - } - catch (const PendingJavaException&) - { - } - catch (const std::exception& e) - { - env.ThrowNew(JavaErrorClass(env), e.what()); - } - catch (...) - { - env.ThrowNew(JavaErrorClass(env), "unknown native exception"); - } - } - } diff --git a/src/jni/field.hpp b/src/jni/field.hpp deleted file mode 100644 index 0f7b714..0000000 --- a/src/jni/field.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include <jni/functions.hpp> -#include <jni/class.hpp> -#include <jni/object.hpp> -#include <jni/type_signature.hpp> -#include <jni/tagging.hpp> - -namespace jni - { - template < class TheTag, class T > - class Field - { - private: - jfieldID& field; - - public: - using TagType = TheTag; - using FieldType = T; - - Field(JNIEnv& env, const Class<TagType>& clazz, const char* name) - : field(GetFieldID(env, *clazz, name, TypeSignature<T>()())) - {} - - operator jfieldID&() const { return field; } - }; - } diff --git a/src/jni/functions.hpp b/src/jni/functions.hpp deleted file mode 100644 index 60e8d67..0000000 --- a/src/jni/functions.hpp +++ /dev/null @@ -1,665 +0,0 @@ -#pragma once - -#include <jni/types.hpp> -#include <jni/errors.hpp> -#include <jni/wrapping.hpp> -#include <jni/ownership.hpp> -#include <jni/typed_methods.hpp> -#include <jni/arraylike.hpp> - -#include <type_traits> -#include <cstdlib> - -namespace jni - { - inline jint GetVersion(JNIEnv& env) - { - return env.GetVersion(); - } - - - inline jclass& DefineClass(JNIEnv& env, const char* name, jobject& loader, const jbyte* buf, jsize size) - { - return *CheckJavaException(env, - Wrap<jclass*>(env.DefineClass(name, Unwrap(loader), buf, Unwrap(size)))); - } - - template < class Array > - auto DefineClass(JNIEnv& env, const char* name, jobject& loader, const Array& buf) - -> std::enable_if_t< IsArraylike<Array>::value, jclass& > - { - return DefineClass(env, name, loader, ArraylikeData(buf), ArraylikeSize(buf)); - } - - inline jclass& FindClass(JNIEnv& env, const char* name) - { - return *CheckJavaException(env, Wrap<jclass*>(env.FindClass(name))); - } - - - inline jmethodID* FromReflectedMethod(JNIEnv& env, jobject* obj) - { - return CheckJavaException(env, - Wrap<jmethodID*>(env.FromReflectedMethod(Unwrap(obj)))); - } - - inline jfieldID* FromReflectedField(JNIEnv& env, jobject* obj) - { - return CheckJavaException(env, - Wrap<jfieldID*>(env.FromReflectedField(Unwrap(obj)))); - } - - inline jobject& ToReflectedMethod(JNIEnv& env, jclass& clazz, jmethodID& method, bool isStatic) - { - return *CheckJavaException(env, - Wrap<jobject*>(env.ToReflectedMethod(Unwrap(clazz), Unwrap(method), isStatic))); - } - - inline jobject& ToReflectedField(JNIEnv& env, jclass& clazz, jfieldID& field, bool isStatic) - { - return *CheckJavaException(env, - Wrap<jobject*>(env.ToReflectedField(Unwrap(clazz), Unwrap(field), isStatic))); - } - - - inline jclass* GetSuperclass(JNIEnv& env, jclass& clazz) - { - return CheckJavaException(env, - Wrap<jclass*>(env.GetSuperclass(Unwrap(clazz)))); - } - - inline bool IsAssignableFrom(JNIEnv& env, jclass& clazz1, jclass& clazz2) - { - return CheckJavaException(env, - env.IsAssignableFrom(Unwrap(clazz1), Unwrap(clazz2))); - } - - - [[noreturn]] inline void Throw(JNIEnv& env, jthrowable& obj) - { - CheckErrorCode(env.Throw(Unwrap(obj))); - throw PendingJavaException(); - } - - [[noreturn]] inline void ThrowNew(JNIEnv& env, jclass& clazz, const char* msg = nullptr) - { - CheckErrorCode(env.ThrowNew(Unwrap(clazz), msg)); - throw PendingJavaException(); - } - - inline bool ExceptionCheck(JNIEnv& env) - { - return env.ExceptionCheck(); - } - - inline jthrowable* ExceptionOccurred(JNIEnv& env) - { - return Wrap<jthrowable*>(env.ExceptionOccurred()); - } - - inline void ExceptionDescribe(JNIEnv& env) - { - env.ExceptionDescribe(); - } - - inline void ExceptionClear(JNIEnv& env) - { - env.ExceptionClear(); - } - - [[noreturn]] inline void FatalError(JNIEnv& env, const char* msg) - { - env.FatalError(msg); - std::abort(); - } - - - inline UniqueLocalFrame PushLocalFrame(JNIEnv& env, jint capacity) - { - CheckJavaExceptionThenErrorCode(env, env.PushLocalFrame(capacity)); - return UniqueLocalFrame(&env, LocalFrameDeleter()); - } - - inline jobject* PopLocalFrame(JNIEnv& env, UniqueLocalFrame&& frame, jobject* result = nullptr) - { - frame.release(); - return CheckJavaException(env, - Wrap<jobject*>(env.PopLocalFrame(Unwrap(result)))); - } - - - template < template < RefDeletionMethod > class Deleter, class T > - UniqueGlobalRef<T, Deleter> NewGlobalRef(JNIEnv& env, T* t) - { - jobject* obj = Wrap<jobject*>(env.NewGlobalRef(Unwrap(t))); - CheckJavaException(env); - if (t && !obj) - throw std::bad_alloc(); - return UniqueGlobalRef<T, Deleter>(reinterpret_cast<T*>(obj), Deleter<&JNIEnv::DeleteGlobalRef>(env)); - } - - template < class T > - UniqueGlobalRef<T> NewGlobalRef(JNIEnv& env, T* t) - { - return NewGlobalRef<DefaultRefDeleter>(env, t); - } - - // Attempt to promote a weak reference to a strong one. Returns an empty result - // if the weak reference has expired. - template < template < RefDeletionMethod > class Deleter, class T, template < RefDeletionMethod > class WeakDeleter > - UniqueGlobalRef<T, Deleter> NewGlobalRef(JNIEnv& env, const UniqueWeakGlobalRef<T, WeakDeleter>& t) - { - jobject* obj = Wrap<jobject*>(env.NewGlobalRef(Unwrap(t))); - CheckJavaException(env); - return UniqueGlobalRef<T, Deleter>(reinterpret_cast<T*>(obj), Deleter<&JNIEnv::DeleteGlobalRef>(env)); - } - - template < class T, template < RefDeletionMethod > class WeakDeleter > - UniqueGlobalRef<T> NewGlobalRef(JNIEnv& env, const UniqueWeakGlobalRef<T, WeakDeleter>& t) - { - return NewGlobalRef<DefaultRefDeleter>(env, t); - } - - template < class T, template < RefDeletionMethod > class Deleter > - void DeleteGlobalRef(JNIEnv& env, UniqueGlobalRef<T, Deleter>&& ref) - { - env.DeleteGlobalRef(Unwrap(ref.release())); - CheckJavaException(env); - } - - - template < class T > - UniqueLocalRef<T> NewLocalRef(JNIEnv& env, T* t) - { - jobject* obj = Wrap<jobject*>(env.NewLocalRef(Unwrap(t))); - CheckJavaException(env); - if (t && !obj) - throw std::bad_alloc(); - return UniqueLocalRef<T>(reinterpret_cast<T*>(obj), DefaultRefDeleter<&JNIEnv::DeleteLocalRef>(env)); - } - - // Attempt to promote a weak reference to a strong one. Returns an empty result - // if the weak reference has expired. - template < class T, template < RefDeletionMethod > class WeakDeleter > - UniqueLocalRef<T> NewLocalRef(JNIEnv& env, const UniqueWeakGlobalRef<T, WeakDeleter>& t) - { - jobject* obj = Wrap<jobject*>(env.NewLocalRef(Unwrap(t))); - CheckJavaException(env); - return UniqueLocalRef<T>(reinterpret_cast<T*>(obj), DefaultRefDeleter<&JNIEnv::DeleteLocalRef>(env)); - } - - template < class T > - void DeleteLocalRef(JNIEnv& env, UniqueLocalRef<T>&& ref) - { - env.DeleteLocalRef(Unwrap(ref.release())); - CheckJavaException(env); - } - - inline void EnsureLocalCapacity(JNIEnv& env, jint capacity) - { - CheckJavaExceptionThenErrorCode(env, env.EnsureLocalCapacity(capacity)); - } - - - template < template < RefDeletionMethod > class Deleter, class T > - UniqueWeakGlobalRef<T, Deleter> NewWeakGlobalRef(JNIEnv& env, T* t) - { - jobject* obj = Wrap<jobject*>(env.NewWeakGlobalRef(Unwrap(t))); - CheckJavaException(env); - if (t && !obj) - throw std::bad_alloc(); - return UniqueWeakGlobalRef<T, Deleter>(reinterpret_cast<T*>(obj), Deleter<&JNIEnv::DeleteWeakGlobalRef>(env)); - } - - template < class T > - UniqueWeakGlobalRef<T> NewWeakGlobalRef(JNIEnv& env, T* t) - { - return NewWeakGlobalRef<DefaultRefDeleter>(env, t); - } - - template < class T, template < RefDeletionMethod > class Deleter > - void DeleteWeakGlobalRef(JNIEnv& env, UniqueWeakGlobalRef<T, Deleter>&& ref) - { - env.DeleteWeakGlobalRef(Unwrap(ref.release())); - CheckJavaException(env); - } - - - inline bool IsSameObject(JNIEnv& env, jobject* ref1, jobject* ref2) - { - return CheckJavaException(env, - env.IsSameObject(Unwrap(ref1), Unwrap(ref2))); - } - - inline jobject& AllocObject(JNIEnv& env, jclass& clazz) - { - return *CheckJavaException(env, - Wrap<jobject*>(env.AllocObject(Unwrap(clazz)))); - } - - template < class... Args > - jobject& NewObject(JNIEnv& env, jclass& clazz, jmethodID& method, Args&&... args) - { - return *CheckJavaException(env, - Wrap<jobject*>(env.NewObject(Unwrap(clazz), Unwrap(method), Unwrap(std::forward<Args>(args))...))); - } - - inline jclass& GetObjectClass(JNIEnv& env, jobject& obj) - { - return *CheckJavaException(env, - Wrap<jclass*>(env.GetObjectClass(Unwrap(obj)))); - } - - inline bool IsInstanceOf(JNIEnv& env, jobject* obj, jclass& clazz) - { - return CheckJavaException(env, - env.IsInstanceOf(Unwrap(obj), Unwrap(clazz))) == JNI_TRUE; - } - - - inline jmethodID& GetMethodID(JNIEnv& env, jclass& clazz, const char* name, const char* sig) - { - return *CheckJavaException(env, - Wrap<jmethodID*>(env.GetMethodID(Unwrap(clazz), name, sig))); - } - - template < class R, class... Args > - std::enable_if_t<!std::is_void<R>::value, R> - CallMethod(JNIEnv& env, jobject* obj, jmethodID& method, Args&&... args) - { - return CheckJavaException(env, - Wrap<R>((env.*(TypedMethods<R>::CallMethod))(Unwrap(obj), Unwrap(method), Unwrap(std::forward<Args>(args))...))); - } - - template < class R, class... Args > - std::enable_if_t<std::is_void<R>::value, R> - CallMethod(JNIEnv& env, jobject* obj, jmethodID& method, Args&&... args) - { - env.CallVoidMethod(Unwrap(obj), Unwrap(method), Unwrap(std::forward<Args>(args))...); - CheckJavaException(env); - } - - template < class R, class... Args > - std::enable_if_t<!std::is_void<R>::value, R> - CallNonvirtualMethod(JNIEnv& env, jobject* obj, jclass& clazz, jmethodID& method, Args&&... args) - { - return CheckJavaException(env, - Wrap<R>((env.*(TypedMethods<R>::CallNonvirtualMethod))(Unwrap(obj), Unwrap(clazz), Unwrap(method), Unwrap(std::forward<Args>(args))...))); - } - - template < class R, class... Args > - std::enable_if_t<std::is_void<R>::value, R> - CallNonvirtualMethod(JNIEnv& env, jobject* obj, jclass& clazz, jmethodID& method, Args&&... args) - { - env.CallNonvirtualVoidMethod(Unwrap(obj), Unwrap(clazz), Unwrap(method), Unwrap(std::forward<Args>(args))...); - CheckJavaException(env); - } - - - inline jfieldID& GetFieldID(JNIEnv& env, jclass& clazz, const char* name, const char* sig) - { - return *CheckJavaException(env, - Wrap<jfieldID*>(env.GetFieldID(Unwrap(clazz), name, sig))); - } - - template < class T > - T GetField(JNIEnv& env, jobject* obj, jfieldID& field) - { - return CheckJavaException(env, - Wrap<T>((env.*(TypedMethods<T>::GetField))(Unwrap(obj), Unwrap(field)))); - } - - template < class T > - void SetField(JNIEnv& env, jobject* obj, jfieldID& field, T value) - { - (env.*(TypedMethods<T>::SetField))(Unwrap(obj), Unwrap(field), Unwrap(value)); - CheckJavaException(env); - } - - - inline jmethodID& GetStaticMethodID(JNIEnv& env, jclass& clazz, const char* name, const char* sig) - { - return *CheckJavaException(env, - Wrap<jmethodID*>(env.GetStaticMethodID(Unwrap(clazz), name, sig))); - } - - template < class R, class... Args > - std::enable_if_t<!std::is_void<R>::value, R> - CallStaticMethod(JNIEnv& env, jclass& clazz, jmethodID& method, Args&&... args) - { - return CheckJavaException(env, - Wrap<R>((env.*(TypedMethods<R>::CallStaticMethod))(Unwrap(clazz), Unwrap(method), Unwrap(std::forward<Args>(args))...))); - } - - template < class R, class... Args > - std::enable_if_t<std::is_void<R>::value, R> - CallStaticMethod(JNIEnv& env, jclass& clazz, jmethodID& method, Args&&... args) - { - env.CallStaticVoidMethod(Unwrap(clazz), Unwrap(method), Unwrap(std::forward<Args>(args))...); - CheckJavaException(env); - } - - - inline jfieldID& GetStaticFieldID(JNIEnv& env, jclass& clazz, const char* name, const char* sig) - { - return *CheckJavaException(env, - Wrap<jfieldID*>(env.GetStaticFieldID(Unwrap(clazz), name, sig))); - } - - template < class T > - T GetStaticField(JNIEnv& env, jclass& clazz, jfieldID& field) - { - return CheckJavaException(env, - Wrap<T>((env.*(TypedMethods<T>::GetStaticField))(Unwrap(clazz), Unwrap(field)))); - } - - template < class T > - void SetStaticField(JNIEnv& env, jclass& clazz, jfieldID& field, T value) - { - (env.*(TypedMethods<T>::SetStaticField))(Unwrap(clazz), Unwrap(field), Unwrap(value)); - CheckJavaException(env); - } - - - inline jstring& NewString(JNIEnv& env, const char16_t* chars, jsize len) - { - return *CheckJavaException(env, - Wrap<jstring*>(env.NewString(Unwrap(chars), Unwrap(len)))); - } - - template < class Array > - auto NewString(JNIEnv& env, const Array& chars) - -> std::enable_if_t< IsArraylike<Array>::value, jstring& > - { - return NewString(env, ArraylikeData(chars), ArraylikeSize(chars)); - } - - inline jsize GetStringLength(JNIEnv& env, jstring& string) - { - return CheckJavaException(env, - Wrap<jsize>(env.GetStringLength(Unwrap(string)))); - } - - inline std::tuple<UniqueStringChars, bool> GetStringChars(JNIEnv& env, jstring& string) - { - ::jboolean isCopy = JNI_FALSE; - const char16_t* result = CheckJavaException(env, - Wrap<const char16_t*>(env.GetStringChars(Unwrap(string), &isCopy))); - return std::make_tuple(UniqueStringChars(result, StringCharsDeleter(env, string)), isCopy); - } - - inline void ReleaseStringChars(JNIEnv& env, jstring& string, UniqueStringChars&& chars) - { - env.ReleaseStringChars(Unwrap(string), Unwrap(chars.release())); - CheckJavaException(env); - } - - inline jstring& NewStringUTF(JNIEnv& env, const char* bytes) - { - return *CheckJavaException(env, - Wrap<jstring*>(env.NewStringUTF(bytes))); - } - - inline jsize GetStringUTFLength(JNIEnv& env, jstring& string) - { - return CheckJavaException(env, - Wrap<jsize>(env.GetStringUTFLength(Unwrap(string)))); - } - - inline std::tuple<UniqueStringUTFChars, bool> GetStringUTFChars(JNIEnv& env, jstring& string) - { - ::jboolean isCopy = JNI_FALSE; - const char* result = CheckJavaException(env, - env.GetStringUTFChars(Unwrap(string), &isCopy)); - return std::make_tuple(UniqueStringUTFChars(result, StringUTFCharsDeleter(env, string)), isCopy); - } - - inline void ReleaseStringUTFChars(JNIEnv& env, jstring& string, UniqueStringUTFChars&& chars) - { - env.ReleaseStringUTFChars(Unwrap(string), chars.release()); - CheckJavaException(env); - } - - inline void GetStringRegion(JNIEnv& env, jstring& string, jsize start, jsize len, char16_t* buf) - { - env.GetStringRegion(Unwrap(string), Unwrap(start), Unwrap(len), Unwrap(buf)); - CheckJavaException(env); - } - - template < class Array > - auto GetStringRegion(JNIEnv& env, jstring& string, jsize start, Array& buf) - -> std::enable_if_t< IsArraylike<Array>::value > - { - GetStringRegion(env, string, start, ArraylikeSize(buf), ArraylikeData(buf)); - } - - inline void GetStringUTFRegion(JNIEnv& env, jstring& string, jsize start, jsize len, char* buf) - { - env.GetStringUTFRegion(Unwrap(string), Unwrap(start), Unwrap(len), buf); - CheckJavaException(env); - } - - template < class Array > - auto GetStringUTFRegion(JNIEnv& env, jstring& string, jsize start, Array& buf) - -> std::enable_if_t< IsArraylike<Array>::value > - { - GetStringUTFRegion(env, string, start, ArraylikeSize(buf), ArraylikeData(buf)); - } - - inline std::tuple<UniqueStringCritical, bool> GetStringCritical(JNIEnv& env, jstring& string) - { - ::jboolean isCopy = JNI_FALSE; - const char16_t* result = CheckJavaException(env, - Wrap<const char16_t*>(env.GetStringCritical(Unwrap(string), &isCopy))); - return std::make_tuple(UniqueStringCritical(result, StringCriticalDeleter(env, string)), isCopy); - } - - inline void ReleaseStringCritical(JNIEnv& env, jstring& string, UniqueStringCritical&& chars) - { - env.ReleaseStringCritical(Unwrap(string), Unwrap(chars.release())); - CheckJavaException(env); - } - - - template < class E > - jsize GetArrayLength(JNIEnv& env, jarray<E>& array) - { - return CheckJavaException(env, - Wrap<jsize>(env.GetArrayLength(Unwrap(array)))); - } - - template < class E > - jarray<E>& NewArray(JNIEnv& env, jsize length) - { - return *CheckJavaException(env, - Wrap<jarray<E>*>((env.*(TypedMethods<E>::NewArray))(Unwrap(length)))); - } - - template < class E > - std::tuple<UniqueArrayElements<E>, bool> GetArrayElements(JNIEnv& env, jarray<E>& array) - { - ::jboolean isCopy = JNI_FALSE; - E* result = CheckJavaException(env, - (env.*(TypedMethods<E>::GetArrayElements))(Unwrap(array), &isCopy)); - return std::make_tuple(UniqueArrayElements<E>(result, ArrayElementsDeleter<E>(env, array)), isCopy); - } - - template < class E > - void ReleaseArrayElements(JNIEnv& env, jarray<E>& array, E* elems) - { - (env.*(TypedMethods<E>::ReleaseArrayElements))(Unwrap(array), elems, JNI_COMMIT); - CheckJavaException(env); - } - - template < class E > - void ReleaseArrayElements(JNIEnv& env, jarray<E>& array, UniqueArrayElements<E>&& elems) - { - (env.*(TypedMethods<E>::ReleaseArrayElements))(Unwrap(array), elems.release(), 0); - CheckJavaException(env); - } - - template < class E > - std::tuple<UniquePrimitiveArrayCritical<E>, bool> GetPrimitiveArrayCritical(JNIEnv& env, jarray<E>& array) - { - ::jboolean isCopy = JNI_FALSE; - void* result = CheckJavaException(env, - env.GetPrimitiveArrayCritical(Unwrap(array), &isCopy)); - return std::make_tuple(UniquePrimitiveArrayCritical<E>(result, PrimitiveArrayCriticalDeleter<E>(env, array)), isCopy); - } - - template < class E > - void ReleasePrimitiveArrayCritical(JNIEnv& env, jarray<E>& array, void* carray) - { - env.ReleasePrimitiveArrayCritical(Unwrap(array), carray, 0); - CheckJavaException(env); - } - - template < class E > - void ReleasePrimitiveArrayCritical(JNIEnv& env, jarray<E>& array, UniquePrimitiveArrayCritical<E>&& carray) - { - env.ReleasePrimitiveArrayCritical(Unwrap(array), carray.release(), JNI_COMMIT); - CheckJavaException(env); - } - - template < class T > - void GetArrayRegion(JNIEnv& env, jarray<T>& array, jsize start, jsize len, T* buf) - { - (env.*(TypedMethods<T>::GetArrayRegion))(Unwrap(array), Unwrap(start), Unwrap(len), buf); - CheckJavaException(env); - } - - template < class T, class Array > - auto GetArrayRegion(JNIEnv& env, jarray<T>& array, jsize start, Array& buf) - -> std::enable_if_t< IsArraylike<Array>::value > - { - GetArrayRegion(env, array, start, ArraylikeSize(buf), ArraylikeData(buf)); - } - - template < class T > - void SetArrayRegion(JNIEnv& env, jarray<T>& array, jsize start, jsize len, const T* buf) - { - (env.*(TypedMethods<T>::SetArrayRegion))(Unwrap(array), Unwrap(start), Unwrap(len), buf); - CheckJavaException(env); - } - - template < class T, class Array > - auto SetArrayRegion(JNIEnv& env, jarray<T>& array, jsize start, const Array& buf) - -> std::enable_if_t< IsArraylike<Array>::value > - { - SetArrayRegion(env, array, start, ArraylikeSize(buf), ArraylikeData(buf)); - } - - - inline jarray<jobject>& NewObjectArray(JNIEnv& env, jsize length, jclass& elementClass, jobject* initialElement = nullptr) - { - return *CheckJavaException(env, - Wrap<jarray<jobject>*>(env.NewObjectArray(Unwrap(length), Unwrap(elementClass), Unwrap(initialElement)))); - } - - inline jobject* GetObjectArrayElement(JNIEnv& env, jarray<jobject>& array, jsize index) - { - return CheckJavaException(env, - Wrap<jobject*>(env.GetObjectArrayElement(Unwrap(array), Unwrap(index)))); - } - - inline void SetObjectArrayElement(JNIEnv& env, jarray<jobject>& array, jsize index, jobject* value) - { - env.SetObjectArrayElement(Unwrap(array), Unwrap(index), Unwrap(value)); - CheckJavaException(env); - } - - - template < class... Methods > - inline void RegisterNatives(JNIEnv& env, jclass& clazz, const Methods&... methods) - { - ::JNINativeMethod unwrapped[sizeof...(methods)] = { Unwrap(methods)... }; - CheckJavaExceptionThenErrorCode(env, - env.RegisterNatives(Unwrap(clazz), unwrapped, sizeof...(methods))); - } - - inline void UnregisterNatives(JNIEnv& env, jclass& clazz) - { - CheckJavaExceptionThenErrorCode(env, env.UnregisterNatives(Unwrap(clazz))); - } - - - inline UniqueMonitor MonitorEnter(JNIEnv& env, jobject* obj) - { - CheckJavaExceptionThenErrorCode(env, env.MonitorEnter(Unwrap(obj))); - return UniqueMonitor(obj, MonitorDeleter(env)); - } - - inline void MonitorExit(JNIEnv& env, UniqueMonitor&& monitor) - { - CheckJavaExceptionThenErrorCode(env, env.MonitorExit(Unwrap(monitor.release()))); - } - - - inline JavaVM& GetJavaVM(JNIEnv& env) - { - JavaVM* result = nullptr; - CheckJavaExceptionThenErrorCode(env, env.GetJavaVM(&result)); - return *result; - } - - - inline jobject& NewDirectByteBuffer(JNIEnv& env, void* address, jlong capacity) - { - return *CheckJavaException(env, - Wrap<jobject*>(env.NewDirectByteBuffer(address, Unwrap(capacity)))); - } - - inline void* GetDirectBufferAddress(JNIEnv& env, jobject& buf) - { - return CheckJavaException(env, - env.GetDirectBufferAddress(Unwrap(buf))); - } - - inline jlong GetDirectBufferCapacity(JNIEnv& env, jobject& buf) - { - return CheckJavaException(env, - env.GetDirectBufferCapacity(Unwrap(buf))); - } - - - inline jobjectRefType GetObjectRefType(JNIEnv& env, jobject* obj) - { - return env.GetObjectRefType(Unwrap(obj)); - } - - - inline UniqueEnv AttachCurrentThread(JavaVM& vm) - { - // Some implementations type the parameter as JNIEnv**, others as void**. - // See https://bugs.openjdk.java.net/browse/JDK-6569899 - struct JNIEnvCast - { - void** operator()(JNIEnv** env, jint (JavaVM::*)(void**, void*)) - { - return reinterpret_cast<void**>(env); - } - - JNIEnv** operator()(JNIEnv** env, jint (JavaVM::*)(JNIEnv**, void*)) - { - return env; - } - }; - - JNIEnv* result; - CheckErrorCode(vm.AttachCurrentThread(JNIEnvCast()(&result, &JavaVM::AttachCurrentThread), nullptr)); - return UniqueEnv(result, JNIEnvDeleter(vm)); - } - - inline void DetachCurrentThread(JavaVM& vm, UniqueEnv&& env) - { - env.release(); - CheckErrorCode(vm.DetachCurrentThread()); - } - - inline JNIEnv& GetEnv(JavaVM& vm, version version = jni_version_1_1) - { - JNIEnv* env = nullptr; - CheckErrorCode(vm.GetEnv(reinterpret_cast<void**>(&env), Unwrap(version))); - return *env; - } - } diff --git a/src/jni/jni.hpp b/src/jni/jni.hpp deleted file mode 100644 index e99325b..0000000 --- a/src/jni/jni.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -// Low-level - -#include <jni/types.hpp> -#include <jni/functions.hpp> -#include <jni/npe.hpp> - - -// High-level - -#include <jni/unique.hpp> -#include <jni/tagging.hpp> -#include <jni/class.hpp> -#include <jni/object.hpp> -#include <jni/string.hpp> -#include <jni/array.hpp> -#include <jni/constructor.hpp> -#include <jni/method.hpp> -#include <jni/static_method.hpp> -#include <jni/field.hpp> -#include <jni/static_field.hpp> -#include <jni/native_method.hpp> -#include <jni/boxing.hpp> -#include <jni/advanced_ownership.hpp> -#include <jni/weak_reference.hpp> diff --git a/src/jni/make.hpp b/src/jni/make.hpp deleted file mode 100644 index f10c9e0..0000000 --- a/src/jni/make.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -namespace jni - { - template < class Result > struct ThingToMake {}; - - template < class Result, class... P > - auto Make(P&&... p) - { - return MakeAnything(ThingToMake<Result>(), std::forward<P>(p)...); - } - } diff --git a/src/jni/method.hpp b/src/jni/method.hpp deleted file mode 100644 index 2e6b69b..0000000 --- a/src/jni/method.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include <jni/functions.hpp> -#include <jni/class.hpp> -#include <jni/object.hpp> -#include <jni/type_signature.hpp> -#include <jni/tagging.hpp> - -namespace jni - { - template < class TheTag, class > - class Method; - - template < class TheTag, class R, class... Args > - class Method< TheTag, R (Args...) > - { - private: - jmethodID& method; - - public: - using TagType = TheTag; - using MethodType = R (Args...); - using ReturnType = R; - - Method(JNIEnv& env, const Class<TagType>& clazz, const char* name) - : method(GetMethodID(env, *clazz, name, TypeSignature<R (Args...)>()())) - {} - - operator jmethodID&() const { return method; } - }; - } diff --git a/src/jni/native_method.hpp b/src/jni/native_method.hpp deleted file mode 100644 index 246db8a..0000000 --- a/src/jni/native_method.hpp +++ /dev/null @@ -1,377 +0,0 @@ -#pragma once - -#include <jni/types.hpp> -#include <jni/errors.hpp> -#include <jni/functions.hpp> -#include <jni/tagging.hpp> -#include <jni/class.hpp> -#include <jni/object.hpp> - -#include <exception> -#include <type_traits> - -namespace jni - { - template < class M, class Enable = void > - struct NativeMethodTraits; - - template < class R, class... Args > - struct NativeMethodTraits< R (Args...) > - { - using Type = R (Args...); - using ResultType = R; - }; - - template < class R, class... Args > - struct NativeMethodTraits< R (*)(Args...) > - : NativeMethodTraits< R (Args...) > {}; - - template < class T, class R, class... Args > - struct NativeMethodTraits< R (T::*)(Args...) const > - : NativeMethodTraits< R (Args...) > {}; - - template < class T, class R, class... Args > - struct NativeMethodTraits< R (T::*)(Args...) > - : NativeMethodTraits< R (Args...) > {}; - - template < class M > - struct NativeMethodTraits< M, std::enable_if_t< std::is_class<M>::value > > - : NativeMethodTraits< decltype(&M::operator()) > {}; - - - /// Low-level, lambda - - template < class M > - auto MakeNativeMethod(const char* name, const char* sig, const M& m, - std::enable_if_t< std::is_class<M>::value >* = nullptr) - { - using FunctionType = typename NativeMethodTraits<M>::Type; - using ResultType = typename NativeMethodTraits<M>::ResultType; - - static FunctionType* method = m; - - auto wrapper = [] (JNIEnv* env, auto... args) - { - try - { - return method(env, args...); - } - catch (...) - { - ThrowJavaError(*env, std::current_exception()); - return ResultType(); - } - }; - - return JNINativeMethod< FunctionType > { name, sig, wrapper }; - } - - - /// Low-level, function pointer - - template < class M, M method > - auto MakeNativeMethod(const char* name, const char* sig) - { - using FunctionType = typename NativeMethodTraits<M>::Type; - using ResultType = typename NativeMethodTraits<M>::ResultType; - - auto wrapper = [] (JNIEnv* env, auto... args) - { - try - { - return method(env, args...); - } - catch (...) - { - ThrowJavaError(*env, std::current_exception()); - return ResultType(); - } - }; - - return JNINativeMethod< FunctionType > { name, sig, wrapper }; - } - - - /// High-level, lambda - - template < class T, T*... > - struct NativeMethodMaker; - - template < class T, class R, class Subject, class... Args > - struct NativeMethodMaker< R (T::*)(JNIEnv&, Subject, Args...) const > - { - template < class M > - auto operator()(const char* name, const M& m) - { - static M method(m); - - auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args) - { - return ReleaseUnique(method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...)); - }; - - return MakeNativeMethod(name, TypeSignature<RemoveUniqueType<R> (std::decay_t<Args>...)>()(), wrapper); - } - }; - - template < class T, class Subject, class... Args > - struct NativeMethodMaker< void (T::*)(JNIEnv&, Subject, Args...) const > - { - template < class M > - auto operator()(const char* name, const M& m) - { - static M method(m); - - auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args) - { - method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...); - }; - - return MakeNativeMethod(name, TypeSignature<void (std::decay_t<Args>...)>()(), wrapper); - } - }; - - template < class M > - auto MakeNativeMethod(const char* name, const M& m) - { - return NativeMethodMaker<decltype(&M::operator())>()(name, m); - } - - - /// High-level, function pointer - - template < class R, class Subject, class... Args, R (*method)(JNIEnv&, Subject, Args...) > - struct NativeMethodMaker< R (JNIEnv&, Subject, Args...), method > - { - auto operator()(const char* name) - { - auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args) - { - return ReleaseUnique(method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...)); - }; - - return MakeNativeMethod(name, TypeSignature<RemoveUniqueType<R> (std::decay_t<Args>...)>()(), wrapper); - } - }; - - template < class Subject, class... Args, void (*method)(JNIEnv&, Subject, Args...) > - struct NativeMethodMaker< void (JNIEnv&, Subject, Args...), method > - { - auto operator()(const char* name) - { - auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args) - { - method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...); - }; - - return MakeNativeMethod(name, TypeSignature<void (std::decay_t<Args>...)>()(), wrapper); - } - }; - - template < class M, M method > - auto MakeNativeMethod(const char* name) - { - using FunctionType = typename NativeMethodTraits<M>::Type; - return NativeMethodMaker<FunctionType, method>()(name); - } - - - /// High-level peer, lambda - - template < class L, class > - class NativePeerLambdaMethod; - - template < class L, class R, class P, class... Args > - class NativePeerLambdaMethod< L, R (L::*)(JNIEnv&, P&, Args...) const > - { - private: - const char* name; - L lambda; - - public: - NativePeerLambdaMethod(const char* n, const L& l) - : name(n), lambda(l) - {} - - template < class Peer, class TagType, class = std::enable_if_t< std::is_same<P, Peer>::value > > - auto operator()(const Field<TagType, jlong>& field) - { - auto wrapper = [field, lambda = lambda] (JNIEnv& env, Object<TagType>& obj, Args... args) - { - return lambda(env, *reinterpret_cast<P*>(obj.Get(env, field)), args...); - }; - - return MakeNativeMethod(name, wrapper); - } - }; - - template < class L > - auto MakeNativePeerMethod(const char* name, const L& lambda, - std::enable_if_t< std::is_class<L>::value >* = nullptr) - { - return NativePeerLambdaMethod<L, decltype(&L::operator())>(name, lambda); - } - - - /// High-level peer, function pointer - - template < class M, M* > - class NativePeerFunctionPointerMethod; - - template < class R, class P, class... Args, R (*method)(JNIEnv&, P&, Args...) > - class NativePeerFunctionPointerMethod< R (JNIEnv&, P&, Args...), method > - { - private: - const char* name; - - public: - NativePeerFunctionPointerMethod(const char* n) - : name(n) - {} - - template < class Peer, class TagType, class = std::enable_if_t< std::is_same<P, Peer>::value > > - auto operator()(const Field<TagType, jlong>& field) - { - auto wrapper = [field] (JNIEnv& env, Object<TagType>& obj, Args... args) - { - return method(env, *reinterpret_cast<P*>(obj.Get(env, field)), args...); - }; - - return MakeNativeMethod(name, wrapper); - } - }; - - template < class M, M method > - auto MakeNativePeerMethod(const char* name, - std::enable_if_t< !std::is_member_function_pointer<M>::value >* = nullptr) - { - using FunctionType = typename NativeMethodTraits<M>::Type; - return NativePeerFunctionPointerMethod<FunctionType, method>(name); - } - - - /// High-level peer, member function pointer - - template < class M, M > - class NativePeerMemberFunctionMethod; - - template < class R, class P, class... Args, R (P::*method)(JNIEnv&, Args...) > - class NativePeerMemberFunctionMethod< R (P::*)(JNIEnv&, Args...), method > - { - private: - const char* name; - - public: - NativePeerMemberFunctionMethod(const char* n) - : name(n) - {} - - template < class Peer, class TagType, class = std::enable_if_t< std::is_same<P, Peer>::value > > - auto operator()(const Field<TagType, jlong>& field) - { - auto wrapper = [field] (JNIEnv& env, Object<TagType>& obj, Args... args) - { - return (reinterpret_cast<P*>(obj.Get(env, field))->*method)(env, args...); - }; - - return MakeNativeMethod(name, wrapper); - } - }; - - template < class M, M method > - auto MakeNativePeerMethod(const char* name, - std::enable_if_t< std::is_member_function_pointer<M>::value >* = nullptr) - { - return NativePeerMemberFunctionMethod<M, method>(name); - } - - - /** - * A registration function for native methods on a "native peer": a long-lived native - * object corresponding to a Java object, usually created when the Java object is created - * and destroyed when the Java object's finalizer runs. - * - * It assumes that the Java object has a field, named by `fieldName`, of Java type `long`, - * which is used to hold a pointer to the native peer. - * - * `Methods` must be a sequence of `NativePeerMethod` instances, instantiated with pointer - * to member functions of the native peer class. For each method in `methods`, a native - * method is bound with a signature corresponding to that of the member function. The - * wrapper for that native method obtains the native peer instance from the Java field and - * calls the native peer method on it, passing along any arguments. - * - * An overload is provided that accepts a Callable object with a unique_ptr result type and - * the names for native creation and finalization methods, allowing creation and disposal of - * the native peer from Java. - * - * For an example of all of the above, see the `examples` directory. - */ - - template < class Peer, class TagType, class... Methods > - void RegisterNativePeer(JNIEnv& env, const Class<TagType>& clazz, const char* fieldName, Methods&&... methods) - { - static Field<TagType, jni::jlong> field { env, clazz, fieldName }; - RegisterNatives(env, *clazz, methods.template operator()<Peer>(field)...); - } - - template < class Peer, class TagType, class > - struct NativePeerHelper; - - template < class Peer, class TagType, class... Args > - struct NativePeerHelper< Peer, TagType, std::unique_ptr<Peer> (JNIEnv&, Args...) > - { - using UniquePeer = std::unique_ptr<Peer>; - using Initializer = UniquePeer (JNIEnv&, Args...); - - auto MakeInitializer(const Field<TagType, jlong>& field, const char* name, Initializer* initializer) const - { - auto wrapper = [field, initializer] (JNIEnv& e, Object<TagType>& obj, std::decay_t<Args>&... args) - { - UniquePeer previous(reinterpret_cast<Peer*>(obj.Get(e, field))); - UniquePeer instance(initializer(e, args...)); - obj.Set(e, field, reinterpret_cast<jlong>(instance.get())); - instance.release(); - }; - - return MakeNativeMethod(name, wrapper); - } - - auto MakeFinalizer(const Field<TagType, jlong>& field, const char* name) const - { - auto wrapper = [field] (JNIEnv& e, Object<TagType>& obj) - { - UniquePeer instance(reinterpret_cast<Peer*>(obj.Get(e, field))); - if (instance) obj.Set(e, field, jlong(0)); - instance.reset(); - }; - - return MakeNativeMethod(name, wrapper); - } - }; - - template < class Peer, class TagType, class Initializer, class... Methods > - void RegisterNativePeer(JNIEnv& env, const Class<TagType>& clazz, const char* fieldName, - Initializer initialize, - const char* initializeMethodName, - const char* finalizeMethodName, - Methods&&... methods) - { - static Field<TagType, jlong> field { env, clazz, fieldName }; - - using InitializerMethodType = typename NativeMethodTraits<Initializer>::Type; - NativePeerHelper<Peer, TagType, InitializerMethodType> helper; - - RegisterNatives(env, *clazz, - helper.MakeInitializer(field, initializeMethodName, initialize), - helper.MakeFinalizer(field, finalizeMethodName), - methods.template operator()<Peer>(field)...); - } - - // Like std::make_unique, but with non-universal reference arguments, so it can be - // explicitly specialized (jni::MakePeer<Peer, jni::jboolean, ...>). - template < class Peer, class... Args > - std::unique_ptr<Peer> MakePeer(jni::JNIEnv& env, Args... args) - { - return std::make_unique<Peer>(env, args...); - } - } diff --git a/src/jni/npe.hpp b/src/jni/npe.hpp deleted file mode 100644 index e5fb9e5..0000000 --- a/src/jni/npe.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include <jni/functions.hpp> - -namespace jni - { - [[noreturn]] inline void ThrowNullPointerException(JNIEnv& env, const char* message = nullptr) - { - ThrowNew(env, FindClass(env, "java/lang/NullPointerException"), message); - } - - template < class T > - void NullCheck(JNIEnv& env, T* ptr, const char* message = nullptr) - { - if (!ptr) ThrowNullPointerException(env, message); - } - - template < class T > - T& SafeDereference(JNIEnv& env, T* ptr, const char* message = nullptr) - { - NullCheck(env, ptr, message); - return *ptr; - } - } diff --git a/src/jni/object.hpp b/src/jni/object.hpp deleted file mode 100644 index cbc93bc..0000000 --- a/src/jni/object.hpp +++ /dev/null @@ -1,153 +0,0 @@ -#pragma once - -#include <jni/functions.hpp> -#include <jni/tagging.hpp> - -#include <cstddef> - -namespace jni - { - template < class TheTag > class Class; - template < class TheTag, class > class Field; - template < class TheTag, class > class Method; - - class ObjectBase - { - protected: - jobject* ptr = nullptr; - - explicit ObjectBase(std::nullptr_t = nullptr) - {} - - explicit ObjectBase(jobject* p) - : ptr(p) - {} - - ~ObjectBase() = default; - - void reset(jobject* p) { ptr = p; } - - public: - explicit operator bool() const { return ptr; } - - friend bool operator==(const ObjectBase& a, const ObjectBase& b) { return a.ptr == b.ptr; } - friend bool operator!=(const ObjectBase& a, const ObjectBase& b) { return !( a == b ); } - - template < class OtherTag > - bool IsInstanceOf(JNIEnv& env, const Class<OtherTag>& clazz) const - { - return jni::IsInstanceOf(env, ptr, *clazz); - } - }; - - template < class TheTag = ObjectTag > - class Object : public TagTraits<TheTag>::SuperType - { - public: - using TagType = TheTag; - using SuperType = typename TagTraits<TheTag>::SuperType; - using UntaggedType = typename TagTraits<TheTag>::UntaggedType; - - protected: - explicit Object(std::nullptr_t = nullptr) - {} - - explicit Object(UntaggedType* p) - : SuperType(p) - {} - - Object(const Object&) = delete; - Object& operator=(const Object&) = delete; - - public: - UntaggedType* get() const { return reinterpret_cast<UntaggedType*>(this->ptr); } - UntaggedType& operator*() const { return *get(); } - - template < class T > - auto Get(JNIEnv& env, const Field<TagType, T>& field) const - -> std::enable_if_t< IsPrimitive<T>::value, T > - { - return GetField<T>(env, get(), field); - } - - template < class T > - auto Get(JNIEnv& env, const Field<TagType, T>& field) const - -> std::enable_if_t< !IsPrimitive<T>::value, Local<T> > - { - return Local<T>(env, reinterpret_cast<typename T::UntaggedType*>(GetField<jobject*>(env, get(), field))); - } - - template < class T > - auto Set(JNIEnv& env, const Field<TagType, T>& field, T value) const - -> std::enable_if_t< IsPrimitive<T>::value > - { - SetField<T>(env, get(), field, value); - } - - template < class Expected, class Actual > - auto Set(JNIEnv& env, const Field<TagType, Expected>& field, const Actual& value) const - -> std::enable_if_t< !IsPrimitive<Expected>::value - && std::is_convertible<const Actual&, const Expected&>::value > - { - SetField<jobject*>(env, get(), field, value.get()); - } - - template < class R, class... ExpectedArgs, class... ActualArgs > - auto Call(JNIEnv& env, const Method<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const - -> std::enable_if_t< IsPrimitive<R>::value - && Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, R > - { - return CallMethod<R>(env, get(), method, Untag(args)...); - } - - template < class R, class... ExpectedArgs, class... ActualArgs > - auto Call(JNIEnv& env, const Method<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const - -> std::enable_if_t< !IsPrimitive<R>::value - && !std::is_void<R>::value - && Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, Local<R> > - { - return Local<R>(env, reinterpret_cast<typename R::UntaggedType*>(CallMethod<jobject*>(env, get(), method, Untag(args)...))); - } - - template < class... ExpectedArgs, class... ActualArgs > - auto Call(JNIEnv& env, const Method<TagType, void (ExpectedArgs...)>& method, const ActualArgs&... args) const - -> std::enable_if_t< Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value > - { - CallMethod<void>(env, get(), method, Untag(args)...); - } - - template < class R, class... ExpectedArgs, class... ActualArgs > - auto CallNonvirtual(JNIEnv& env, const Class<TagType>& clazz, const Method<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const - -> std::enable_if_t< IsPrimitive<R>::value - && Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, R > - { - return CallNonvirtualMethod<R>(env, get(), clazz, method, Untag(args)...); - } - - template < class R, class... ExpectedArgs, class... ActualArgs > - auto CallNonvirtual(JNIEnv& env, const Class<TagType>& clazz, const Method<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const - -> std::enable_if_t< !IsPrimitive<R>::value - && !std::is_void<R>::value - && Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, Local<R> > - { - return Local<R>(env, reinterpret_cast<typename R::UntaggedType*>(CallNonvirtualMethod<jobject*>(env, get(), clazz, method, Untag(args)...))); - } - - template < class... ExpectedArgs, class... ActualArgs > - auto CallNonvirtual(JNIEnv& env, const Class<TagType>& clazz, const Method<TagType, void (ExpectedArgs...)>& method, const ActualArgs&... args) const - -> std::enable_if_t< Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value > - { - CallNonvirtualMethod<void>(env, get(), clazz, method, Untag(args)...); - } - }; - - template < class OutTagType, class T > - Local<Object<OutTagType>> Cast(JNIEnv& env, const Class<OutTagType>& clazz, const T& object) - { - if (!object.IsInstanceOf(env, clazz)) - { - ThrowNew(env, FindClass(env, "java/lang/ClassCastException")); - } - return Local<Object<OutTagType>>(env, reinterpret_cast<typename Object<OutTagType>::UntaggedType*>(NewLocal(env, object).release())); - } - } diff --git a/src/jni/ownership.hpp b/src/jni/ownership.hpp deleted file mode 100644 index 56241df..0000000 --- a/src/jni/ownership.hpp +++ /dev/null @@ -1,224 +0,0 @@ -#pragma once - -#include <jni/types.hpp> -#include <jni/wrapping.hpp> -#include <jni/typed_methods.hpp> - -namespace jni - { - struct LocalFrameDeleter - { - void operator()(JNIEnv* env) const - { - if (env) - { - env->PopLocalFrame(nullptr); - } - } - }; - - using UniqueLocalFrame = std::unique_ptr< JNIEnv, LocalFrameDeleter >; - - - using RefDeletionMethod = void (JNIEnv::*)(::jobject); - - template < RefDeletionMethod DeleteRef > - class DefaultRefDeleter - { - private: - JNIEnv* env = nullptr; - - public: - DefaultRefDeleter() = default; - DefaultRefDeleter(JNIEnv& e) : env(&e) {} - - void operator()(jobject* p) const - { - if (p) - { - assert(env); - (env->*DeleteRef)(Unwrap(p)); - } - } - }; - - - template < class T, template < RefDeletionMethod > class Deleter = DefaultRefDeleter > - using UniqueGlobalRef = std::unique_ptr< T, Deleter<&JNIEnv::DeleteGlobalRef> >; - - template < class T, template < RefDeletionMethod > class Deleter = DefaultRefDeleter > - using UniqueWeakGlobalRef = std::unique_ptr< T, Deleter<&JNIEnv::DeleteWeakGlobalRef> >; - - // Not parameterized by Deleter because local references should be short-lived enough - // that DefaultRefDeleter suffices in all cases. - template < class T > - using UniqueLocalRef = std::unique_ptr< T, DefaultRefDeleter<&JNIEnv::DeleteLocalRef> >; - - - class StringCharsDeleter - { - private: - JNIEnv* env = nullptr; - jstring* string = nullptr; - - public: - StringCharsDeleter() = default; - StringCharsDeleter(JNIEnv& e, jstring& s) : env(&e), string(&s) {} - - void operator()(const char16_t* p) const - { - if (p) - { - assert(env); - assert(string); - env->ReleaseStringChars(Unwrap(string), Unwrap(p)); - } - } - }; - - using UniqueStringChars = std::unique_ptr< const char16_t, StringCharsDeleter >; - - - class StringUTFCharsDeleter - { - private: - JNIEnv* env = nullptr; - jstring* string = nullptr; - - public: - StringUTFCharsDeleter() = default; - StringUTFCharsDeleter(JNIEnv& e, jstring& s) : env(&e), string(&s) {} - - void operator()(const char* p) const - { - if (p) - { - assert(env); - assert(string); - env->ReleaseStringUTFChars(Unwrap(string), p); - } - } - }; - - using UniqueStringUTFChars = std::unique_ptr< const char, StringUTFCharsDeleter >; - - - class StringCriticalDeleter - { - private: - JNIEnv* env = nullptr; - jstring* string = nullptr; - - public: - StringCriticalDeleter() = default; - StringCriticalDeleter(JNIEnv& e, jstring& s) : env(&e), string(&s) {} - - void operator()(const char16_t* p) const - { - if (p) - { - assert(env); - assert(string); - env->ReleaseStringCritical(Unwrap(string), Unwrap(p)); - } - } - }; - - using UniqueStringCritical = std::unique_ptr< const char16_t, StringCriticalDeleter >; - - - template < class E > - class ArrayElementsDeleter - { - private: - JNIEnv* env = nullptr; - jarray<E>* array = nullptr; - - public: - ArrayElementsDeleter() = default; - ArrayElementsDeleter(JNIEnv& e, jarray<E>& a) : env(&e), array(&a) {} - - void operator()(E* p) const - { - if (p) - { - assert(env); - assert(array); - (env->*(TypedMethods<E>::ReleaseArrayElements))(Unwrap(array), p, JNI_ABORT); - } - } - }; - - template < class E > - using UniqueArrayElements = std::unique_ptr< E, ArrayElementsDeleter<E> >; - - - template < class E > - class PrimitiveArrayCriticalDeleter - { - private: - JNIEnv* env = nullptr; - jarray<E>* array = nullptr; - - public: - PrimitiveArrayCriticalDeleter() = default; - PrimitiveArrayCriticalDeleter(JNIEnv& e, jarray<E>& a) : env(&e), array(&a) {} - - void operator()(void* p) const - { - if (p) - { - assert(env); - assert(array); - env->ReleasePrimitiveArrayCritical(Unwrap(array), p, JNI_ABORT); - } - } - }; - - template < class E > - using UniquePrimitiveArrayCritical = std::unique_ptr< void, PrimitiveArrayCriticalDeleter<E> >; - - - class MonitorDeleter - { - private: - JNIEnv* env = nullptr; - - public: - MonitorDeleter() = default; - MonitorDeleter(JNIEnv& e) : env(&e) {} - - void operator()(jobject* p) const - { - if (p) - { - assert(env); - env->MonitorExit(Unwrap(p)); - } - } - }; - - using UniqueMonitor = std::unique_ptr< jobject, MonitorDeleter >; - - - class JNIEnvDeleter - { - private: - JavaVM* vm = nullptr; - - public: - JNIEnvDeleter() = default; - JNIEnvDeleter(JavaVM& v) : vm(&v) {} - - void operator()(JNIEnv* p) const - { - if (p) - { - assert(vm); - vm->DetachCurrentThread(); - } - } - }; - - using UniqueEnv = std::unique_ptr< JNIEnv, JNIEnvDeleter >; - } diff --git a/src/jni/static_field.hpp b/src/jni/static_field.hpp deleted file mode 100644 index 137c9f6..0000000 --- a/src/jni/static_field.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include <jni/functions.hpp> -#include <jni/class.hpp> -#include <jni/object.hpp> -#include <jni/type_signature.hpp> -#include <jni/tagging.hpp> - -namespace jni - { - template < class TheTag, class T > - class StaticField - { - private: - jfieldID& field; - - public: - using TagType = TheTag; - using FieldType = T; - - StaticField(JNIEnv& env, const Class<TagType>& clazz, const char* name) - : field(GetStaticFieldID(env, *clazz, name, TypeSignature<T>()())) - {} - - operator jfieldID&() const { return field; } - }; - } diff --git a/src/jni/static_method.hpp b/src/jni/static_method.hpp deleted file mode 100644 index 97d8274..0000000 --- a/src/jni/static_method.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include <jni/functions.hpp> -#include <jni/class.hpp> -#include <jni/object.hpp> -#include <jni/type_signature.hpp> -#include <jni/tagging.hpp> - -namespace jni - { - template < class TheTag, class > - class StaticMethod; - - template < class TheTag, class R, class... Args > - class StaticMethod< TheTag, R (Args...) > - { - private: - jmethodID& method; - - public: - using TagType = TheTag; - using MethodType = R (Args...); - using ReturnType = R; - - StaticMethod(JNIEnv& env, const Class<TagType>& clazz, const char* name) - : method(GetStaticMethodID(env, *clazz, name, TypeSignature<R (Args...)>()())) - {} - - operator jmethodID&() const { return method; } - }; - } diff --git a/src/jni/string.hpp b/src/jni/string.hpp deleted file mode 100644 index 5be4423..0000000 --- a/src/jni/string.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include <jni/object.hpp> -#include <jni/array.hpp> -#include <jni/make.hpp> -#include <jni/npe.hpp> -#include <jni/string_conversion.hpp> - -namespace jni - { - using String = Object<StringTag>; - - inline std::u16string MakeAnything(ThingToMake<std::u16string>, JNIEnv& env, const String& string) - { - NullCheck(env, string.get()); - std::u16string result(jni::GetStringLength(env, *string), char16_t()); - jni::GetStringRegion(env, *string, 0, result); - return result; - } - - inline std::string MakeAnything(ThingToMake<std::string>, JNIEnv& env, const String& string) - { - return convertUTF16ToUTF8(Make<std::u16string>(env, string)); - } - - inline Local<String> MakeAnything(ThingToMake<String>, JNIEnv& env, const std::u16string& string) - { - return Local<String>(env, &NewString(env, string)); - } - - inline Local<String> MakeAnything(ThingToMake<String>, JNIEnv& env, const std::string& string) - { - return Make<String>(env, convertUTF8ToUTF16(string)); - } - } diff --git a/src/jni/string_conversion.hpp b/src/jni/string_conversion.hpp deleted file mode 100644 index 78974ef..0000000 --- a/src/jni/string_conversion.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -// If you want to supply your own UTF-8 <-> UTF-16 conversion routines, create a header file -// that can be found at <jni/string_conversion.hpp> and will be found first in the lookup chain. - -#include <string> -#include <locale> -#include <codecvt> - -namespace jni - { - inline std::u16string convertUTF8ToUTF16(const std::string& string) - { - return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().from_bytes(string); - } - - inline std::string convertUTF16ToUTF8(const std::u16string& string) - { - return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().to_bytes(string); - } - } diff --git a/src/jni/tagging.hpp b/src/jni/tagging.hpp deleted file mode 100644 index 15c9116..0000000 --- a/src/jni/tagging.hpp +++ /dev/null @@ -1,131 +0,0 @@ -#pragma once - -#include <jni/traits.hpp> -#include <jni/unique.hpp> - -#include <type_traits> - -namespace jni - { - class ObjectBase; - template < class Tag > class Object; - template < class E, class = void > class Array; - template < class > struct TypeSignature; - - - struct ObjectTag - { - static constexpr auto Name() { return "java/lang/Object"; } - }; - - struct StringTag - { - static constexpr auto Name() { return "java/lang/String"; } - }; - - struct ClassTag - { - static constexpr auto Name() { return "java/lang/Class"; } - }; - - template < class T > - struct ArrayTag - { - static constexpr auto Name() { return TypeSignature<Array<T>>()(); } - }; - - - template < class Tag, class = int > - struct SuperTag - { - using Type = ObjectTag; - }; - - template < class Tag > - struct SuperTag< Tag, decltype(std::declval<typename Tag::SuperTag>(), 0) > - { - using Type = typename Tag::SuperTag; - }; - - template < class Tag, class Enable = void > - struct TagTraits - { - using SuperType = Object<typename SuperTag<Tag>::Type>; - using UntaggedType = jobject; - }; - - template <> - struct TagTraits< ObjectTag > - { - using SuperType = ObjectBase; - using UntaggedType = jobject; - }; - - template <> - struct TagTraits< StringTag > - { - using SuperType = Object<ObjectTag>; - using UntaggedType = jstring; - }; - - template <> - struct TagTraits< ClassTag > - { - using SuperType = Object<ObjectTag>; - using UntaggedType = jclass; - }; - - template < class E > - struct TagTraits< ArrayTag<E>, std::enable_if_t<IsPrimitive<E>::value> > - { - using SuperType = Object<ObjectTag>; - using UntaggedType = jarray<E>; - }; - - template < class Tag > - struct TagTraits< ArrayTag<Object<Tag>> > - { - using SuperType = Object<ObjectTag>; - using UntaggedType = jarray<jobject>; - }; - - - template < class T > - auto Tag(JNIEnv&, T primitive) - -> std::enable_if_t< IsPrimitive<T>::value, T > - { - return primitive; - } - - template < class T, class U > - auto Tag(JNIEnv& env, U* u) - -> std::enable_if_t< !IsPrimitive<T>::value, Input<T> > - { - return Input<T>(env, u); - } - - template < class T, class U > - auto Tag(JNIEnv& env, U& u) - -> std::enable_if_t< !IsPrimitive<T>::value, Input<T> > - { - return Input<T>(env, &u); - } - - - template < class T > - auto Untag(T primitive) - -> std::enable_if_t< IsPrimitive<T>::value, T > - { - return primitive; - } - - template < class T > - auto Untag(const T& t) - -> std::enable_if_t< !IsPrimitive<T>::value, decltype(t.get()) > - { - return t.get(); - } - - template < class T > - using UntaggedType = decltype(Untag(std::declval<T>())); - } diff --git a/src/jni/traits.hpp b/src/jni/traits.hpp deleted file mode 100644 index 23e0b2f..0000000 --- a/src/jni/traits.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include <jni/types.hpp> - -#include <type_traits> - -namespace jni - { - template < class T > struct IsPrimitive : std::false_type {}; - template <> struct IsPrimitive< jboolean > : std::true_type {}; - template <> struct IsPrimitive< jbyte > : std::true_type {}; - template <> struct IsPrimitive< jchar > : std::true_type {}; - template <> struct IsPrimitive< jshort > : std::true_type {}; - template <> struct IsPrimitive< jint > : std::true_type {}; - template <> struct IsPrimitive< jlong > : std::true_type {}; - template <> struct IsPrimitive< jfloat > : std::true_type {}; - template <> struct IsPrimitive< jdouble > : std::true_type {}; - - template < class T > struct IsReference : std::false_type {}; - template <> struct IsReference< jobject > : std::true_type {}; - template <> struct IsReference< jclass > : std::true_type {}; - template <> struct IsReference< jstring > : std::true_type {}; - template <> struct IsReference< jthrowable > : std::true_type {}; - - template < class T > struct IsArray : std::false_type {}; - template < class E > struct IsArray< jarray<E> > : std::true_type {}; - - template < class... > struct Conjunction : std::true_type {}; - template < class B1 > struct Conjunction<B1> : B1 {}; - template < class B1, class... Bn > struct Conjunction<B1, Bn...> - : std::conditional_t<bool(B1::value), Conjunction<Bn...>, B1> {}; - - template < class T > T& AsLvalue(T&& x) { return x; } - } diff --git a/src/jni/type_signature.hpp b/src/jni/type_signature.hpp deleted file mode 100644 index 6c8320f..0000000 --- a/src/jni/type_signature.hpp +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include <jni/functions.hpp> -#include <jni/object.hpp> -#include <jni/array.hpp> - -namespace jni - { - template < char... chars > - struct StringLiteral - { - operator const char *() const - { - static const char result[] = { chars..., 0 }; - return result; - } - }; - - constexpr std::size_t StringLiteralLength(const char * str, std::size_t len = 0) - { - return str[0] ? StringLiteralLength(str + 1, len + 1) : len; - } - - template < class, class > - struct TagLiteralImpl; - - template < class Tag, std::size_t... Is > - struct TagLiteralImpl< Tag, std::index_sequence<Is...> > - { - using Value = StringLiteral< Tag::Name()[Is]... >; - }; - - template < class Tag > - using TagLiteral = typename TagLiteralImpl< Tag, std::make_index_sequence<StringLiteralLength(Tag::Name())> >::Value; - - template < char... As, char... Bs > - constexpr auto Concat(const StringLiteral<As...>&, - const StringLiteral<Bs...>&) - { - return StringLiteral<As..., Bs...>(); - } - - template < class A, class B, class... Rest > - constexpr auto Concat(const A& a, - const B& b, - const Rest&... rest) - { - return Concat(Concat(a, b), rest...); - } - - template < class > struct TypeSignature; - - template <> struct TypeSignature< jboolean > { constexpr auto operator()() const { return StringLiteral<'Z'>(); } }; - template <> struct TypeSignature< jbyte > { constexpr auto operator()() const { return StringLiteral<'B'>(); } }; - template <> struct TypeSignature< jchar > { constexpr auto operator()() const { return StringLiteral<'C'>(); } }; - template <> struct TypeSignature< jshort > { constexpr auto operator()() const { return StringLiteral<'S'>(); } }; - template <> struct TypeSignature< jint > { constexpr auto operator()() const { return StringLiteral<'I'>(); } }; - template <> struct TypeSignature< jlong > { constexpr auto operator()() const { return StringLiteral<'J'>(); } }; - template <> struct TypeSignature< jfloat > { constexpr auto operator()() const { return StringLiteral<'F'>(); } }; - template <> struct TypeSignature< jdouble > { constexpr auto operator()() const { return StringLiteral<'D'>(); } }; - template <> struct TypeSignature< void > { constexpr auto operator()() const { return StringLiteral<'V'>(); } }; - - template < class TheTag > - struct TypeSignature< Object<TheTag> > - { - constexpr auto operator()() const - { - return Concat(StringLiteral<'L'>(), TagLiteral<TheTag>(), StringLiteral<';'>()); - } - }; - - template < class E > - struct TypeSignature< Array<E> > - { - constexpr auto operator()() const - { - return Concat(StringLiteral<'['>(), TypeSignature<E>()()); - } - }; - - template < class R, class... Args > - struct TypeSignature< R (Args...) > - { - constexpr auto operator()() const - { - return Concat(StringLiteral<'('>(), TypeSignature<Args>()()..., StringLiteral<')'>(), TypeSignature<R>()()); - } - }; - } diff --git a/src/jni/typed_methods.hpp b/src/jni/typed_methods.hpp deleted file mode 100644 index 412c2d7..0000000 --- a/src/jni/typed_methods.hpp +++ /dev/null @@ -1,147 +0,0 @@ -#pragma once - -#include <jni.h> - -namespace jni - { - template < class R > struct TypedMethods; - - template <> struct TypedMethods< jobject* > - { - static constexpr auto CallMethod = &JNIEnv::CallObjectMethod; - static constexpr auto CallNonvirtualMethod = &JNIEnv::CallNonvirtualObjectMethod; - static constexpr auto GetField = &JNIEnv::GetObjectField; - static constexpr auto SetField = &JNIEnv::SetObjectField; - static constexpr auto CallStaticMethod = &JNIEnv::CallStaticObjectMethod; - static constexpr auto GetStaticField = &JNIEnv::GetStaticObjectField; - static constexpr auto SetStaticField = &JNIEnv::SetStaticObjectField; - }; - - template <> struct TypedMethods< jboolean > - { - static constexpr auto CallMethod = &JNIEnv::CallBooleanMethod; - static constexpr auto CallNonvirtualMethod = &JNIEnv::CallNonvirtualBooleanMethod; - static constexpr auto GetField = &JNIEnv::GetBooleanField; - static constexpr auto SetField = &JNIEnv::SetBooleanField; - static constexpr auto CallStaticMethod = &JNIEnv::CallStaticBooleanMethod; - static constexpr auto GetStaticField = &JNIEnv::GetStaticBooleanField; - static constexpr auto SetStaticField = &JNIEnv::SetStaticBooleanField; - static constexpr auto NewArray = &JNIEnv::NewBooleanArray; - static constexpr auto GetArrayElements = &JNIEnv::GetBooleanArrayElements; - static constexpr auto ReleaseArrayElements = &JNIEnv::ReleaseBooleanArrayElements; - static constexpr auto GetArrayRegion = &JNIEnv::GetBooleanArrayRegion; - static constexpr auto SetArrayRegion = &JNIEnv::SetBooleanArrayRegion; - }; - - template <> struct TypedMethods< jbyte > - { - static constexpr auto CallMethod = &JNIEnv::CallByteMethod; - static constexpr auto CallNonvirtualMethod = &JNIEnv::CallNonvirtualByteMethod; - static constexpr auto GetField = &JNIEnv::GetByteField; - static constexpr auto SetField = &JNIEnv::SetByteField; - static constexpr auto CallStaticMethod = &JNIEnv::CallStaticByteMethod; - static constexpr auto GetStaticField = &JNIEnv::GetStaticByteField; - static constexpr auto SetStaticField = &JNIEnv::SetStaticByteField; - static constexpr auto NewArray = &JNIEnv::NewByteArray; - static constexpr auto GetArrayElements = &JNIEnv::GetByteArrayElements; - static constexpr auto ReleaseArrayElements = &JNIEnv::ReleaseByteArrayElements; - static constexpr auto GetArrayRegion = &JNIEnv::GetByteArrayRegion; - static constexpr auto SetArrayRegion = &JNIEnv::SetByteArrayRegion; - }; - - template <> struct TypedMethods< jchar > - { - static constexpr auto CallMethod = &JNIEnv::CallCharMethod; - static constexpr auto CallNonvirtualMethod = &JNIEnv::CallNonvirtualCharMethod; - static constexpr auto GetField = &JNIEnv::GetCharField; - static constexpr auto SetField = &JNIEnv::SetCharField; - static constexpr auto CallStaticMethod = &JNIEnv::CallStaticCharMethod; - static constexpr auto GetStaticField = &JNIEnv::GetStaticCharField; - static constexpr auto SetStaticField = &JNIEnv::SetStaticCharField; - static constexpr auto NewArray = &JNIEnv::NewCharArray; - static constexpr auto GetArrayElements = &JNIEnv::GetCharArrayElements; - static constexpr auto ReleaseArrayElements = &JNIEnv::ReleaseCharArrayElements; - static constexpr auto GetArrayRegion = &JNIEnv::GetCharArrayRegion; - static constexpr auto SetArrayRegion = &JNIEnv::SetCharArrayRegion; - }; - - template <> struct TypedMethods< jshort > - { - static constexpr auto CallMethod = &JNIEnv::CallShortMethod; - static constexpr auto CallNonvirtualMethod = &JNIEnv::CallNonvirtualShortMethod; - static constexpr auto GetField = &JNIEnv::GetShortField; - static constexpr auto SetField = &JNIEnv::SetShortField; - static constexpr auto CallStaticMethod = &JNIEnv::CallStaticShortMethod; - static constexpr auto GetStaticField = &JNIEnv::GetStaticShortField; - static constexpr auto SetStaticField = &JNIEnv::SetStaticShortField; - static constexpr auto NewArray = &JNIEnv::NewShortArray; - static constexpr auto GetArrayElements = &JNIEnv::GetShortArrayElements; - static constexpr auto ReleaseArrayElements = &JNIEnv::ReleaseShortArrayElements; - static constexpr auto GetArrayRegion = &JNIEnv::GetShortArrayRegion; - static constexpr auto SetArrayRegion = &JNIEnv::SetShortArrayRegion; - }; - - template <> struct TypedMethods< jint > - { - static constexpr auto CallMethod = &JNIEnv::CallIntMethod; - static constexpr auto CallNonvirtualMethod = &JNIEnv::CallNonvirtualIntMethod; - static constexpr auto GetField = &JNIEnv::GetIntField; - static constexpr auto SetField = &JNIEnv::SetIntField; - static constexpr auto CallStaticMethod = &JNIEnv::CallStaticIntMethod; - static constexpr auto GetStaticField = &JNIEnv::GetStaticIntField; - static constexpr auto SetStaticField = &JNIEnv::SetStaticIntField; - static constexpr auto NewArray = &JNIEnv::NewIntArray; - static constexpr auto GetArrayElements = &JNIEnv::GetIntArrayElements; - static constexpr auto ReleaseArrayElements = &JNIEnv::ReleaseIntArrayElements; - static constexpr auto GetArrayRegion = &JNIEnv::GetIntArrayRegion; - static constexpr auto SetArrayRegion = &JNIEnv::SetIntArrayRegion; - }; - - template <> struct TypedMethods< jlong > - { - static constexpr auto CallMethod = &JNIEnv::CallLongMethod; - static constexpr auto CallNonvirtualMethod = &JNIEnv::CallNonvirtualLongMethod; - static constexpr auto GetField = &JNIEnv::GetLongField; - static constexpr auto SetField = &JNIEnv::SetLongField; - static constexpr auto CallStaticMethod = &JNIEnv::CallStaticLongMethod; - static constexpr auto GetStaticField = &JNIEnv::GetStaticLongField; - static constexpr auto SetStaticField = &JNIEnv::SetStaticLongField; - static constexpr auto NewArray = &JNIEnv::NewLongArray; - static constexpr auto GetArrayElements = &JNIEnv::GetLongArrayElements; - static constexpr auto ReleaseArrayElements = &JNIEnv::ReleaseLongArrayElements; - static constexpr auto GetArrayRegion = &JNIEnv::GetLongArrayRegion; - static constexpr auto SetArrayRegion = &JNIEnv::SetLongArrayRegion; - }; - - template <> struct TypedMethods< jfloat > - { - static constexpr auto CallMethod = &JNIEnv::CallFloatMethod; - static constexpr auto CallNonvirtualMethod = &JNIEnv::CallNonvirtualFloatMethod; - static constexpr auto GetField = &JNIEnv::GetFloatField; - static constexpr auto SetField = &JNIEnv::SetFloatField; - static constexpr auto CallStaticMethod = &JNIEnv::CallStaticFloatMethod; - static constexpr auto GetStaticField = &JNIEnv::GetStaticFloatField; - static constexpr auto SetStaticField = &JNIEnv::SetStaticFloatField; - static constexpr auto NewArray = &JNIEnv::NewFloatArray; - static constexpr auto GetArrayElements = &JNIEnv::GetFloatArrayElements; - static constexpr auto ReleaseArrayElements = &JNIEnv::ReleaseFloatArrayElements; - static constexpr auto GetArrayRegion = &JNIEnv::GetFloatArrayRegion; - static constexpr auto SetArrayRegion = &JNIEnv::SetFloatArrayRegion; - }; - - template <> struct TypedMethods< jdouble > - { - static constexpr auto CallMethod = &JNIEnv::CallDoubleMethod; - static constexpr auto CallNonvirtualMethod = &JNIEnv::CallNonvirtualDoubleMethod; - static constexpr auto GetField = &JNIEnv::GetDoubleField; - static constexpr auto SetField = &JNIEnv::SetDoubleField; - static constexpr auto CallStaticMethod = &JNIEnv::CallStaticDoubleMethod; - static constexpr auto GetStaticField = &JNIEnv::GetStaticDoubleField; - static constexpr auto SetStaticField = &JNIEnv::SetStaticDoubleField; - static constexpr auto NewArray = &JNIEnv::NewDoubleArray; - static constexpr auto GetArrayElements = &JNIEnv::GetDoubleArrayElements; - static constexpr auto ReleaseArrayElements = &JNIEnv::ReleaseDoubleArrayElements; - static constexpr auto GetArrayRegion = &JNIEnv::GetDoubleArrayRegion; - static constexpr auto SetArrayRegion = &JNIEnv::SetDoubleArrayRegion; - }; - } diff --git a/src/jni/types.hpp b/src/jni/types.hpp deleted file mode 100644 index 035155e..0000000 --- a/src/jni/types.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once - -#include <cstddef> -#include <cassert> -#include <memory> -#include <stdexcept> - -#include <jni.h> - -namespace jni - { - // Not using bool because its size is implementation-defined, and a defined size - // is necessary for array operations. - - using ::jboolean; - - const jboolean jni_false = 0; - const jboolean jni_true = 1; - - using ::jbyte; - using ::jchar; - using ::jshort; - using ::jint; - using ::jlong; - using ::jfloat; - using ::jdouble; - - using jsize = std::size_t; - - struct jobject - { - jobject() = delete; - ~jobject() = delete; - jobject(const jobject&) = delete; - jobject& operator=(const jobject&) = delete; - }; - - struct jclass : public jobject {}; - struct jstring : public jobject {}; - struct jthrowable : public jobject {}; - - template < class T > - struct jarray : public jobject {}; - - using jobjectArray = jarray< jobject >; - using jbooleanArray = jarray< jboolean >; - using jbyteArray = jarray< jbyte >; - using jcharArray = jarray< jchar >; - using jshortArray = jarray< jshort >; - using jintArray = jarray< jint >; - using jlongArray = jarray< jlong >; - using jfloatArray = jarray< jfloat >; - using jdoubleArray = jarray< jdouble >; - - using jfieldID = std::pointer_traits< ::jfieldID >::element_type; - using jmethodID = std::pointer_traits< ::jmethodID >::element_type; - - using ::jobjectRefType; - - using ::JavaVM; - using ::JNIEnv; - - template < class T > - struct JNINativeMethod; - - template < class R, class... Args > - struct JNINativeMethod< R (JNIEnv*, jclass*, Args...) > - { - const char* name; - const char* signature; - R (*fnPtr)(JNIEnv*, jclass*, Args...); - }; - - template < class R, class... Args > - struct JNINativeMethod< R (JNIEnv*, jobject*, Args...) > - { - const char* name; - const char* signature; - R (*fnPtr)(JNIEnv*, jobject*, Args...); - }; - - enum version : jint - { - jni_version_1_1 = version(JNI_VERSION_1_1), - jni_version_1_2 = version(JNI_VERSION_1_2), - jni_version_1_4 = version(JNI_VERSION_1_4), - jni_version_1_6 = version(JNI_VERSION_1_6), - }; - - enum error : jint - { - jni_ok = error(JNI_OK), - jni_err = error(JNI_ERR), - jni_edetached = error(JNI_EDETACHED), - jni_eversion = error(JNI_EVERSION), - }; - } diff --git a/src/jni/unique.hpp b/src/jni/unique.hpp deleted file mode 100644 index 2abf490..0000000 --- a/src/jni/unique.hpp +++ /dev/null @@ -1,220 +0,0 @@ -#pragma once - -namespace jni - { - /* - Ownership type and main interface for high-level references. Client code using the high-level - API will most often work with values of this class template, using the following aliases: - - * Global<P>, a.k.a. Unique<T, DefaultRefDeleter<&JNIEnv::DeleteGlobalRef>>, - * Weak<P>, a.k.a. Unique<T, DefaultRefDeleter<&JNIEnv::DeleteWeakGlobalRef>>, - * Local<P>, a.k.a. Unique<T, LocalRefDeleter>, - - where P is Object<>, Class<>, or Array<>. - - `Unique` is an ownership class with a deletion policy that's parameterized both - by the appropriate method to delete the reference (global, weak, or local) and - (for global and weak references), a choice about how to obtain the JNIEnv that's - necessary to call the deletion method. The default policy is to delete the reference - using the same JNIEnv as was passed to the constructor, but in cases where the - object may be deleted on a different thread (commonly, the Java finalizer thread), - EnvGettingDeleter or EnvAttachingDeleter may be needed. - - Object<>, Class<>, or Array<> -- the underlying and inherited types used for - the template parameter T -- are not publicly constructible or destructible. This - is to ensure that code works only with ownership types which release the reference - at an appropriate time. Our experience has shown that this is important even for - local references; the default JVM cleanup behaviors for local references are not - enough to ensure that the local reference table never overflows. - - You may also pass or receive C++ references when you wish to borrow rather than take - ownership. For example, receiving parameters for a native method implementation should be - C++ references, reflecting the fact that JVM implementations prohibit explicitly releasing - this form of local reference. However, if you need to store or copy the reference, you - will need to use a method such as `NewGlobalRef` that copies at the reference level. - `Unique`, `Object<>`, etc., are not themselves copyable. - */ - template < class T, class D > - class Unique : public T - { - private: - D deleter; - - Unique(const Unique&) = delete; - Unique& operator=(const Unique&) = delete; - - public: - using Base = T; - using UntaggedType = typename T::UntaggedType; - - explicit Unique(std::nullptr_t ptr = nullptr) - : T(ptr), - deleter() {} - - explicit Unique(JNIEnv& env, UntaggedType* ptr) - : T(ptr), - deleter(env) {} - - Unique(Unique&& other) - : T(other.release()), - deleter(std::move(other.get_deleter())) {} - - template < class U > - Unique(Unique<U, D>&& other, std::enable_if_t<std::is_convertible<const U&, const T&>::value>* = nullptr) - : T(other.release()), - deleter(std::move(other.get_deleter())) {} - - ~Unique() - { - reset(); - } - - Unique& operator=(Unique&& other) - { - reset(other.release()); - deleter = std::move(other.deleter); - return *this; - } - - void reset(UntaggedType* ptr = nullptr) - { - UntaggedType* current = this->get(); - T::reset(ptr); - if (current) - { - get_deleter()(current); - } - } - - UntaggedType* release() - { - UntaggedType* current = this->get(); - T::reset(nullptr); - return current; - } - - D& get_deleter() { return deleter; } - const D& get_deleter() const { return deleter; } - }; - - - template < class T, template < RefDeletionMethod > class Deleter = DefaultRefDeleter > - using Global = Unique< T, Deleter<&JNIEnv::DeleteGlobalRef> >; - - template < class T, template < RefDeletionMethod > class Deleter = DefaultRefDeleter > - using Weak = Unique< T, Deleter<&JNIEnv::DeleteWeakGlobalRef> >; - - // Not parameterized by Deleter because local references should be short-lived enough - // that DefaultRefDeleter suffices in all cases. - template < class T > - using Local = Unique< T, DefaultRefDeleter<&JNIEnv::DeleteLocalRef> >; - - - // Special case for JNI-provided input parameters to native methods, which apparently - // should not be explicitly deleted (https://bugs.chromium.org/p/chromium/issues/detail?id=506850). - struct NullDeleter - { - NullDeleter() = default; - NullDeleter(JNIEnv&) {} - void operator()(jobject*) const {} - }; - - template < class T > - using Input = Unique< T, NullDeleter >; - - - template < class T > - struct RemoveUnique - { - using Type = T; - }; - - template < class T, class D > - struct RemoveUnique< Unique<T, D> > - { - using Type = T; - }; - - template < class T > - using RemoveUniqueType = typename RemoveUnique<T>::Type; - - - template < class T > - auto ReleaseUnique(T primitive) - { - return primitive; - } - - template < class T, class D > - auto ReleaseUnique(Unique<T, D>&& t) - { - return t.release(); - } - - - template < template < RefDeletionMethod > class Deleter, class T > - auto NewGlobal(JNIEnv& env, const T& t) - { - return Global<RemoveUniqueType<T>, Deleter>(env, reinterpret_cast<typename T::UntaggedType*>(jni::NewGlobalRef(env, t.get()).release())); - } - - template < class T > - auto NewGlobal(JNIEnv& env, const T& t) - { - return NewGlobal<DefaultRefDeleter>(env, t); - } - - // Attempt to promote a weak reference to a strong one. Returns an empty result - // if the weak reference has expired. - // - // Beware that the semantics of JNI weak references are weaker than is typically - // desired: a JNI weak reference may still be promoted to a non-null strong reference - // even during finalization. Consider using jni::WeakReference<T> instead. - template < template < RefDeletionMethod > class Deleter, class T, template < RefDeletionMethod > class WeakDeleter > - Global<T, Deleter> NewGlobal(JNIEnv& env, const Weak<T, WeakDeleter>& t) - { - jobject* obj = Wrap<jobject*>(env.NewGlobalRef(Unwrap(t->get()))); - CheckJavaException(env); - return Global<T, Deleter>(env, obj); - } - - template < class T > - Global<T> NewGlobal(JNIEnv& env, const Weak<T>& t) - { - return NewGlobal<DefaultRefDeleter>(env, t); - } - - - template < template < RefDeletionMethod > class Deleter, class T > - auto NewWeak(JNIEnv& env, const T& t) - { - return Weak<RemoveUniqueType<T>, Deleter>(env, reinterpret_cast<typename T::UntaggedType*>(jni::NewWeakGlobalRef(env, t.get()).release())); - } - - template < class T > - auto NewWeak(JNIEnv& env, const T& t) - { - return NewWeak<DefaultRefDeleter>(env, t); - } - - - template < class T > - auto NewLocal(JNIEnv& env, const T& t) - { - return Local<RemoveUniqueType<T>>(env, reinterpret_cast<typename T::UntaggedType*>(jni::NewLocalRef(env, t.get()).release())); - } - - // Attempt to promote a weak reference to a strong one. Returns an empty result - // if the weak reference has expired. - // - // Beware that the semantics of JNI weak references are weaker than is typically - // desired: a JNI weak reference may still be promoted to a non-null strong reference - // even during finalization. Consider using jni::WeakReference<T> instead. - template < class T, template < RefDeletionMethod > class WeakDeleter > - Local<T> NewLocal(JNIEnv& env, const Weak<T, WeakDeleter>& t) - { - jobject* obj = Wrap<jobject*>(env.NewLocalRef(Unwrap(t->get()))); - CheckJavaException(env); - return Local<T>(env, obj); - } - } diff --git a/src/jni/weak_reference.hpp b/src/jni/weak_reference.hpp deleted file mode 100644 index 2536272..0000000 --- a/src/jni/weak_reference.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include <jni/class.hpp> -#include <jni/object.hpp> - -namespace jni - { - struct WeakReferenceTag { static constexpr auto Name() { return "java/lang/ref/WeakReference"; } }; - - // Wraps a JNI global reference to a java.lang.ref.WeakReference, producing an ownership class - // similar to jni::Weak<T> (JNI's weak global reference), but with more reliable promotion semantics. - // Whereas a JNI weak global reference may still be promoted to a strong reference even during - // finalization, leading to potential use-after-free errors, a WeakReference cannot. - template < class T, template < RefDeletionMethod > class Deleter = DefaultRefDeleter > - class WeakReference - { - private: - Global<Object<WeakReferenceTag>, Deleter> reference; - - public: - WeakReference(JNIEnv& env, const T& referent) - { - static auto& klass = Class<WeakReferenceTag>::Singleton(env); - static auto constructor = klass.GetConstructor<Object<>>(env); - reference = NewGlobal<Deleter>(env, klass.New(env, constructor, referent)); - } - - Local<T> get(JNIEnv& env) - { - if (!reference) - { - return Local<T>(); - } - - static auto& klass = Class<WeakReferenceTag>::Singleton(env); - static auto get = klass.template GetMethod<Object<> ()>(env, "get"); - return Local<T>(env, reinterpret_cast<typename T::UntaggedType*>(reference.Call(env, get).release())); - } - }; - } diff --git a/src/jni/wrapping.hpp b/src/jni/wrapping.hpp deleted file mode 100644 index be2989f..0000000 --- a/src/jni/wrapping.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#pragma once - -#include <cstddef> -#include <cassert> -#include <limits> -#include <memory> -#include <utility> - -#include <jni.h> - -namespace jni - { - template < class W > struct Wrapper; - - template < class W, class U > - auto Wrap(U&& u) - { - return Wrapper<W>().Wrap(std::forward<U>(u)); - } - - template < class W > - auto Unwrap(W&& w) - { - return Wrapper<typename std::decay<W>::type>().Unwrap(std::forward<W>(w)); - } - - template < class T > - using UnwrappedType = decltype(Unwrap<T>(std::declval<T>())); - - - template < class T > - struct PrimitiveTypeWrapper - { - T Wrap(T t) const { return t; } - T Unwrap(T t) const { return t; } - }; - - template <> struct Wrapper< jboolean > : PrimitiveTypeWrapper< jboolean > {}; - template <> struct Wrapper< jbyte > : PrimitiveTypeWrapper< jbyte > {}; - template <> struct Wrapper< jchar > : PrimitiveTypeWrapper< jchar > {}; - template <> struct Wrapper< jshort > : PrimitiveTypeWrapper< jshort > {}; - template <> struct Wrapper< jint > : PrimitiveTypeWrapper< jint > {}; - template <> struct Wrapper< jlong > : PrimitiveTypeWrapper< jlong > {}; - template <> struct Wrapper< jfloat > : PrimitiveTypeWrapper< jfloat > {}; - template <> struct Wrapper< jdouble > : PrimitiveTypeWrapper< jdouble > {}; - - - template <> - struct Wrapper<const char16_t*> - { - const char16_t* Wrap(const jchar* s) const { return reinterpret_cast<const char16_t*>(s); } - const jchar* Unwrap(const char16_t* s) const { return reinterpret_cast<const jchar*>(s); } - }; - - template <> - struct Wrapper<char16_t*> - { - char16_t* Wrap(jchar* s) const { return reinterpret_cast<char16_t*>(s); } - jchar* Unwrap(char16_t* s) const { return reinterpret_cast<jchar*>(s); } - }; - - - template <> - struct Wrapper<jsize> - { - jsize Wrap(::jsize s) const - { - if (s < 0) - throw std::range_error("::jsize < 0"); - return static_cast<jsize>(s); - } - - ::jsize Unwrap(jsize s) const - { - if (s > std::numeric_limits<::jsize>::max()) - throw std::range_error("jsize > max"); - return static_cast<::jsize>(s); - } - }; - - - template < class W, class U > - struct ReferenceTypeWrapper - { - W* Wrap(U u) const { return reinterpret_cast<W*>(u); } - U Unwrap(W* w) const { return reinterpret_cast<U>(w); } - }; - - template <> struct Wrapper< jobject* > : ReferenceTypeWrapper< jobject, ::jobject > {}; - template <> struct Wrapper< jclass* > : ReferenceTypeWrapper< jclass, ::jclass > {}; - template <> struct Wrapper< jstring* > : ReferenceTypeWrapper< jstring, ::jstring > {}; - template <> struct Wrapper< jthrowable* > : ReferenceTypeWrapper< jthrowable, ::jthrowable > {}; - - template <> struct Wrapper< jarray< jobject >* > : ReferenceTypeWrapper< jarray< jobject >, ::jobjectArray > {}; - template <> struct Wrapper< jarray< jboolean >* > : ReferenceTypeWrapper< jarray< jboolean >, ::jbooleanArray > {}; - template <> struct Wrapper< jarray< jbyte >* > : ReferenceTypeWrapper< jarray< jbyte >, ::jbyteArray > {}; - template <> struct Wrapper< jarray< jchar >* > : ReferenceTypeWrapper< jarray< jchar >, ::jcharArray > {}; - template <> struct Wrapper< jarray< jshort >* > : ReferenceTypeWrapper< jarray< jshort >, ::jshortArray > {}; - template <> struct Wrapper< jarray< jint >* > : ReferenceTypeWrapper< jarray< jint >, ::jintArray > {}; - template <> struct Wrapper< jarray< jlong >* > : ReferenceTypeWrapper< jarray< jlong >, ::jlongArray > {}; - template <> struct Wrapper< jarray< jfloat >* > : ReferenceTypeWrapper< jarray< jfloat >, ::jfloatArray > {}; - template <> struct Wrapper< jarray< jdouble >* > : ReferenceTypeWrapper< jarray< jdouble >, ::jdoubleArray > {}; - - template <> struct Wrapper< jfieldID* > : ReferenceTypeWrapper< jfieldID, ::jfieldID > {}; - template <> struct Wrapper< jmethodID* > : ReferenceTypeWrapper< jmethodID, ::jmethodID > {}; - - - // Allow references to be unwrapped to pointers to the underlying type, but not the - // reverse, because dereferences should be explicit, with null checks where necessary. - - template < class W, class U > - struct ReferenceTypeUnwrapper - { - U Unwrap(W& w) const { return reinterpret_cast<U>(&w); } - }; - - template <> struct Wrapper< jobject > : ReferenceTypeUnwrapper< jobject, ::jobject > {}; - template <> struct Wrapper< jclass > : ReferenceTypeUnwrapper< jclass, ::jclass > {}; - template <> struct Wrapper< jstring > : ReferenceTypeUnwrapper< jstring, ::jstring > {}; - template <> struct Wrapper< jthrowable > : ReferenceTypeUnwrapper< jthrowable, ::jthrowable > {}; - - template <> struct Wrapper< jarray< jobject > > : ReferenceTypeUnwrapper< jarray< jobject >, ::jobjectArray > {}; - template <> struct Wrapper< jarray< jboolean > > : ReferenceTypeUnwrapper< jarray< jboolean >, ::jbooleanArray > {}; - template <> struct Wrapper< jarray< jbyte > > : ReferenceTypeUnwrapper< jarray< jbyte >, ::jbyteArray > {}; - template <> struct Wrapper< jarray< jchar > > : ReferenceTypeUnwrapper< jarray< jchar >, ::jcharArray > {}; - template <> struct Wrapper< jarray< jshort > > : ReferenceTypeUnwrapper< jarray< jshort >, ::jshortArray > {}; - template <> struct Wrapper< jarray< jint > > : ReferenceTypeUnwrapper< jarray< jint >, ::jintArray > {}; - template <> struct Wrapper< jarray< jlong > > : ReferenceTypeUnwrapper< jarray< jlong >, ::jlongArray > {}; - template <> struct Wrapper< jarray< jfloat > > : ReferenceTypeUnwrapper< jarray< jfloat >, ::jfloatArray > {}; - template <> struct Wrapper< jarray< jdouble > > : ReferenceTypeUnwrapper< jarray< jdouble >, ::jdoubleArray > {}; - - template <> struct Wrapper< jfieldID > : ReferenceTypeUnwrapper< jfieldID, ::jfieldID > {}; - template <> struct Wrapper< jmethodID > : ReferenceTypeUnwrapper< jmethodID, ::jmethodID > {}; - - - template < class T, class R, class... Args > - struct Wrapper< JNINativeMethod< R (JNIEnv*, T*, Args...) > > - { - ::JNINativeMethod Unwrap(JNINativeMethod<R (JNIEnv*, T*, Args...)> method) const - { - return { const_cast<char*>(method.name), const_cast<char*>(method.signature), reinterpret_cast<void*>(method.fnPtr) }; - } - }; - - - template <> - struct Wrapper<version> - { - version Wrap(::jint v) const { return static_cast<version>(v); } - ::jint Unwrap(version v) const { return static_cast<::jint>(v); } - }; - } diff --git a/src/lime_ffi.cpp b/src/lime_ffi.cpp deleted file mode 100644 index cdfb7ac..0000000 --- a/src/lime_ffi.cpp +++ /dev/null @@ -1,481 +0,0 @@ -/** - @file lime_ffi.cpp - - @author Johan Pascal - - @copyright Copyright (C) 2018 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -#include "lime/lime_ffi.h" -#include "lime/lime.hpp" -#include "lime_log.hpp" -#include "bctoolbox/exception.hh" -#include "lime_settings.hpp" -#include "lime_defines.hpp" -#include "lime_double_ratchet_protocol.hpp" - -extern "C" { - -using namespace::std; -using namespace::lime; -/***** - * Opaque structutes definitions: used to let the C side store and send back pointers to the C++ objects or closures - *****/ -/** - * @brief encapsulate a unique pointer to limeManager in an opaque structure - * - */ -struct lime_manager_struct { - std::unique_ptr<LimeManager> context; /**< the encapsulated lime manager held in a unique ptr so we're sure to destroy it easily */ -}; - -/** - * @brief an opaque structure holding the lime cpp closure to be used to forward the X3DH server's response to lime - */ -struct lime_ffi_data_struct { - const limeX3DHServerResponseProcess responseProcess; /**< a callback to forward the response to lib lime */ - lime_ffi_data_struct(const limeX3DHServerResponseProcess &response) : responseProcess(response) {}; -}; - -/***** - * Local Helpers functions - *****/ -static lime::CurveId ffi2lime_CurveId(const enum lime_ffi_CurveId curve) { - switch (curve) { - case lime_ffi_CurveId_c25519: - return lime::CurveId::c25519; - case lime_ffi_CurveId_c448: - return lime::CurveId::c448; - default: - return lime::CurveId::unset; - } -} - -static enum lime_ffi_CallbackReturn lime2ffi_CallbackReturn(const lime::CallbackReturn cbReturn) { - switch (cbReturn) { - case lime::CallbackReturn::success: - return lime_ffi_CallbackReturn_success; - case lime::CallbackReturn::fail: - default : - return lime_ffi_CallbackReturn_fail; - } -} - -static lime::EncryptionPolicy ffi2lime_EncryptionPolicy(const enum lime_ffi_EncryptionPolicy encryptionPolicy) { - switch (encryptionPolicy) { - case lime_ffi_EncryptionPolicy_DRMessage : - return lime::EncryptionPolicy::DRMessage; - case lime_ffi_EncryptionPolicy_cipherMessage : - return lime::EncryptionPolicy::cipherMessage; - case lime_ffi_EncryptionPolicy_optimizeUploadSize : - return lime::EncryptionPolicy::optimizeUploadSize; - case lime_ffi_EncryptionPolicy_optimizeGlobalBandwidth : - return lime::EncryptionPolicy::optimizeGlobalBandwidth; - default: - return lime::EncryptionPolicy::optimizeUploadSize; - } -} - -static enum lime_ffi_PeerDeviceStatus lime2ffi_PeerDeviceStatus(const lime::PeerDeviceStatus status) { - switch (status) { - case lime::PeerDeviceStatus::untrusted : - return lime_ffi_PeerDeviceStatus_untrusted; - break; - case lime::PeerDeviceStatus::trusted : - return lime_ffi_PeerDeviceStatus_trusted; - break; - case lime::PeerDeviceStatus::unsafe : - return lime_ffi_PeerDeviceStatus_unsafe; - break; - case lime::PeerDeviceStatus::unknown : - return lime_ffi_PeerDeviceStatus_unknown; - break; - case lime::PeerDeviceStatus::fail : - default: - return lime_ffi_PeerDeviceStatus_fail; - break; - } -} - -static lime::PeerDeviceStatus ffi2lime_PeerDeviceStatus(const enum lime_ffi_PeerDeviceStatus status) { - switch (status) { - case lime_ffi_PeerDeviceStatus_untrusted : - return lime::PeerDeviceStatus::untrusted; - break; - case lime_ffi_PeerDeviceStatus_trusted : - return lime::PeerDeviceStatus::trusted; - break; - case lime_ffi_PeerDeviceStatus_unsafe : - return lime::PeerDeviceStatus::unsafe; - break; - case lime_ffi_PeerDeviceStatus_unknown : - return lime::PeerDeviceStatus::unknown; - break; - case lime_ffi_PeerDeviceStatus_fail : - default: - return lime::PeerDeviceStatus::fail; - break; - } -} - - - -/***** - * API doxygen doc in lime_ff.h - * All functions would just intercept any exception rising and return an error if there were - *****/ -int lime_ffi_processX3DHServerResponse(lime_ffi_data_t userData, const int code, const uint8_t *response, const size_t response_size) { - try { - // turn the response into a vector<uint8_t> - auto body = std::vector<uint8_t>(response, response+response_size); - // forward it to lime using the closure stored in the userData structure - userData->responseProcess(code, body); - // we're done with the userData, delete it to be sure to free the closure - delete(userData); - } catch (exception const &e) { // just catch anything - LIME_LOGE<<"FFI failed to process X3DH server response: "<<e.what(); - return LIME_FFI_INTERNAL_ERROR; - } - return LIME_FFI_SUCCESS; -} - -int lime_ffi_manager_init(lime_manager_t * const manager, const char *db, const lime_ffi_X3DHServerPostData X3DH_post_data, void *userData) { - - // create a lambda to manage the X3DH post, it shall just tweak the arguments to match C capabilities and forward the request to the provided C X3DH_post_data function - limeX3DHServerPostData X3DHServerPost([userData, X3DH_post_data](const std::string &url, const std::string &from, const std::vector<uint8_t> &message, const limeX3DHServerResponseProcess responseProcess) { - - // use a dedicated structure to store the closure given by lime to process the response - // so the C code can hold it through a pointer to an opaque structure - // this struct will be freed after the responseProcess has been called - lime_ffi_data_t limeData = new lime_ffi_data_struct(responseProcess); - - X3DH_post_data(userData, // forward the userData pointer - limeData, // pass our pointer, it will be given back to the lime_ffi_processX3DHServerResponse function - url.data(), from.data(), - message.data(), message.size()); - }); - - try { - // LimeManager object is encapsulated in an opaque structure so the C code can keep track of it and provide it back when needed - // the struct is freed by the destroy function(which will also destroy the LimeManager object) - *manager = new lime_manager_struct(); - (*manager)->context = std::unique_ptr<LimeManager>(new LimeManager(std::string(db), X3DHServerPost)); - } catch (exception const &e) { // catch anything - LIME_LOGE<<"FFI failed to create the lime manager: "<<e.what(); - return LIME_FFI_INTERNAL_ERROR; - } - - return LIME_FFI_SUCCESS; -} - -int lime_ffi_create_user(lime_manager_t manager, const char *localDeviceId, const char *x3dhServerUrl, const enum lime_ffi_CurveId curve, const uint16_t OPkInitialBatchSize, - const lime_ffi_Callback callback, void *callbackUserData) { - - // just intercept the lime callback, convert the arguments to the correct types, add the userData and forward it to the C side - limeCallback cb([callback, callbackUserData](const lime::CallbackReturn status, const std::string message){ - callback(callbackUserData, lime2ffi_CallbackReturn(status), message.data()); - }); - - try { - manager->context->create_user(std::string(localDeviceId), std::string(x3dhServerUrl), ffi2lime_CurveId(curve), OPkInitialBatchSize, cb); - } catch (BctbxException const &e) { - LIME_LOGE<<"FFI failed to create user: "<<e.str(); - return LIME_FFI_INTERNAL_ERROR; - } catch (exception const &e) { // catch anything - LIME_LOGE<<"FFI failed to create user: "<<e.what(); - return LIME_FFI_INTERNAL_ERROR; - } - return LIME_FFI_SUCCESS; -} - -int lime_ffi_delete_user(lime_manager_t manager, const char *localDeviceId, const lime_ffi_Callback callback, void *callbackUserData) { - - // just intercept the lime callback, convert the arguments to the correct types, add the userData and forward it to the C side - limeCallback cb([callback, callbackUserData](const lime::CallbackReturn status, const std::string message){ - callback(callbackUserData, lime2ffi_CallbackReturn(status), message.data()); - }); - - try { - manager->context->delete_user(std::string(localDeviceId), cb); - } catch (BctbxException const &e) { - LIME_LOGE<<"FFI failed to delete user: "<<e.str(); - return LIME_FFI_INTERNAL_ERROR; - } catch (exception const &e) { // catch anything - LIME_LOGE<<"FFI failed to delete user: "<<e.what(); - return LIME_FFI_INTERNAL_ERROR; - } - return LIME_FFI_SUCCESS; -} - -int lime_ffi_is_user(lime_manager_t manager, const char *localDeviceId) { - try { - if (manager->context->is_user(std::string(localDeviceId))) { - return LIME_FFI_SUCCESS; - } else { - return LIME_FFI_USER_NOT_FOUND; - } - } catch (exception const &e) { // catch anything (BctbxException are already taken care of by is_user, but other kind may arise) - LIME_LOGE<<"FFI failed to delete user: "<<e.what(); - return LIME_FFI_INTERNAL_ERROR; - } -} - -int lime_ffi_encryptOutBuffersMaximumSize(const size_t plainMessageSize, const enum lime_ffi_CurveId curve, size_t *DRmessageSize, size_t *cipherMessageSize) { - /* cipherMessage maximum size is plain message size + auth tag size */ - *cipherMessageSize = plainMessageSize + lime::settings::DRMessageAuthTagSize; - - /* DRmessage maximum size is : - * DRmessage header size + X3DH init size + MAX(plain message size, RandomSeed Size) + auth tag size */ - *DRmessageSize = std::max(plainMessageSize, lime::settings::DRrandomSeedSize) + lime::settings::DRMessageAuthTagSize; - - switch (curve) { - case lime_ffi_CurveId_c25519: -#ifdef EC25519_ENABLED - *DRmessageSize += lime::double_ratchet_protocol::headerSize<C255>() + lime::double_ratchet_protocol::X3DHinitSize<C255>(true); -#else /* EC25519_ENABLED */ - return LIME_FFI_INVALID_CURVE_ARGUMENT; -#endif /* EC25519_ENABLED */ - break; - - case lime_ffi_CurveId_c448: -#ifdef EC448_ENABLED - *DRmessageSize += lime::double_ratchet_protocol::headerSize<C448>() + lime::double_ratchet_protocol::X3DHinitSize<C448>(true); -#else /* EC448_ENABLED */ - return LIME_FFI_INVALID_CURVE_ARGUMENT; -#endif /* EC448_ENBALED*/ - break; - - default : - return LIME_FFI_INVALID_CURVE_ARGUMENT; - } - - return LIME_FFI_SUCCESS; -} - -int lime_ffi_encrypt(lime_manager_t manager, const char *localDeviceId, - const uint8_t *const recipientUserId, const size_t recipientUserIdSize, - lime_ffi_RecipientData_t *const recipients, const size_t recipientsSize, - const uint8_t *const plainMessage, const size_t plainMessageSize, - uint8_t *const cipherMessage, size_t *cipherMessageSize, - const lime_ffi_Callback callback, void *callbackUserData, - enum lime_ffi_EncryptionPolicy encryptionPolicy) { - - - /* create shared of recipients and cipher message, ownership is then taken by lime during encrypt until we get into the callback */ - auto l_recipients = make_shared<std::vector<RecipientData>>(); - // copy the whole list of recipients to a std::vector<recipientData> - for (size_t i=0; i<recipientsSize; i++) { - l_recipients->emplace_back(recipients[i].deviceId); - // also propagate fail status spotting this entry to be ignored by the encryption engine - switch (recipients[i].peerStatus) { - case lime_ffi_PeerDeviceStatus_fail : - l_recipients->back().peerStatus = lime::PeerDeviceStatus::fail; - break; - default : // any other status would be anyway overwritten, so do not bother and let it be unknown as it default at construction - break; - } - } - auto l_cipherMessage = make_shared<std::vector<uint8_t>>(); - - /* capture : - * - callback and its userData so we can forward the lime's callback to the C side - * - recipients, cipherMessage and cipherMessageSize so we can the copy the DRmessage and cipherMessage from lime's encryp output to them (recipients size is actually stored in l_recipients as they have the same size) - * - l_recipients and l_cipherMessage so we can access them in the callback to get the encryption's output - * - * Note: all of the captured variables are pointers, so we copy capture them and not get their reference - */ - limeCallback cb([callback, callbackUserData, recipients, cipherMessage, cipherMessageSize, l_recipients, l_cipherMessage](const lime::CallbackReturn status, const std::string message){ - // if we have room to copy back the cipher Message to the given C buffer, do it. - if (*cipherMessageSize >= l_cipherMessage->size()) { - std::copy_n(l_cipherMessage->begin(), l_cipherMessage->size(), cipherMessage); - *cipherMessageSize = l_cipherMessage->size(); - } else { - callback(callbackUserData, lime_ffi_CallbackReturn_fail, "cipherMessage buffer is too small to hold result"); - } - - size_t i=0; - // loop on all l_recipients, the are matching the indices of recipients array as it was built from it - for (const auto &l_recipient:(*l_recipients)) { - // copy back the DR messages(with their sizes) - if (l_recipient.DRmessage.size() <= recipients[i].DRmessageSize) { - std::copy_n(l_recipient.DRmessage.begin(), l_recipient.DRmessage.size(), recipients[i].DRmessage); - recipients[i].DRmessageSize = l_recipient.DRmessage.size(); - } else { - callback(callbackUserData, lime_ffi_CallbackReturn_fail, "DRmessage buffer is too small to hold result"); - return; - } - // and the peer device status - recipients[i].peerStatus = lime2ffi_PeerDeviceStatus(l_recipient.peerStatus); - i++; - } - callback(callbackUserData, lime2ffi_CallbackReturn(status), message.data()); - }); - - /* encrypts */ - try { - manager->context->encrypt(std::string(localDeviceId), make_shared<std::vector<uint8_t>>(recipientUserId, recipientUserId+recipientUserIdSize), l_recipients, make_shared<std::vector<uint8_t>>(plainMessage, plainMessage+plainMessageSize), l_cipherMessage, cb, ffi2lime_EncryptionPolicy(encryptionPolicy)); - } catch (BctbxException const &e) { - LIME_LOGE<<"FFI failed to encrypt: "<<e.str(); - return LIME_FFI_INTERNAL_ERROR; - } catch (exception const &e) { // catch anything - LIME_LOGE<<"FFI failed to encrypt: "<<e.what(); - return LIME_FFI_INTERNAL_ERROR; - } - - return LIME_FFI_SUCCESS; -} - -enum lime_ffi_PeerDeviceStatus lime_ffi_decrypt(lime_manager_t manager, const char *localDeviceId, - const uint8_t *const recipientUserId, const size_t recipientUserIdSize, - const char *senderDeviceId, - const uint8_t *const DRmessage, const size_t DRmessageSize, - const uint8_t *const cipherMessage, const size_t cipherMessageSize, - uint8_t *const plainMessage, size_t *plainMessageSize) { - - try { - std::vector<uint8_t> l_plainMessage{}; - auto ret = manager->context->decrypt(std::string(localDeviceId), std::vector<uint8_t>(recipientUserId, recipientUserId+recipientUserIdSize), std::string(senderDeviceId), std::vector<uint8_t>(DRmessage, DRmessage+DRmessageSize), std::vector<uint8_t>(cipherMessage, cipherMessage+cipherMessageSize), l_plainMessage); - - if (l_plainMessage.size()<=*plainMessageSize) { - std::copy_n(l_plainMessage.data(), l_plainMessage.size(), plainMessage); - *plainMessageSize = l_plainMessage.size(); - } - return lime2ffi_PeerDeviceStatus(ret); - } catch (BctbxException const &e) { - LIME_LOGE<<"FFI failed to encrypt: "<<e.str(); - return lime_ffi_PeerDeviceStatus_fail; - } catch (exception const &e) { // catch anything - LIME_LOGE<<"FFI failed to encrypt: "<<e.what(); - return lime_ffi_PeerDeviceStatus_fail; - } -} - - -int lime_ffi_manager_destroy(lime_manager_t manager) { - manager->context = nullptr; - delete (manager); - return LIME_FFI_SUCCESS; -} - -int lime_ffi_get_selfIdentityKey(lime_manager_t manager, const char *localDeviceId, uint8_t *const Ik, size_t *IkSize) { - try { - std::vector<uint8_t> l_Ik{}; - manager->context->get_selfIdentityKey(std::string(localDeviceId), l_Ik); - - if (l_Ik.size() <= *IkSize) { - std::copy_n(l_Ik.begin(), l_Ik.size(), Ik); - *IkSize = l_Ik.size(); - return LIME_FFI_SUCCESS; - } else { - *IkSize = 0; - return LIME_FFI_OUTPUT_BUFFER_TOO_SMALL; - } - } catch (BctbxException const &e) { - LIME_LOGE<<"FFI failed to get self Identity key: "<<e.str(); - return LIME_FFI_INTERNAL_ERROR; - } catch (exception const &e) { // catch anything - LIME_LOGE<<"FFI failed to get self Identity key: "<<e.what(); - return LIME_FFI_INTERNAL_ERROR; - } -} - -int lime_ffi_set_peerDeviceStatus(lime_manager_t manager, const char *peerDeviceId, const uint8_t *const Ik, const size_t IkSize, enum lime_ffi_PeerDeviceStatus status) { - try { - if (IkSize > 0) { // we have an Ik - manager->context->set_peerDeviceStatus(std::string(peerDeviceId), std::vector<uint8_t>(Ik, Ik+IkSize), ffi2lime_PeerDeviceStatus(status)); - } else { // no Ik provided - manager->context->set_peerDeviceStatus(std::string(peerDeviceId), ffi2lime_PeerDeviceStatus(status)); - } - return LIME_FFI_SUCCESS; - } catch (BctbxException const &e) { - LIME_LOGE<<"FFI failed to set self Identity key: "<<e.str(); - return LIME_FFI_INTERNAL_ERROR; - } catch (exception const &e) { // catch anything - LIME_LOGE<<"FFI failed to set self Identity key: "<<e.what(); - return LIME_FFI_INTERNAL_ERROR; - } -} - -enum lime_ffi_PeerDeviceStatus lime_ffi_get_peerDeviceStatus(lime_manager_t manager, const char *peerDeviceId) { - return (lime2ffi_PeerDeviceStatus(manager->context->get_peerDeviceStatus(std::string(peerDeviceId)))); -} - -int lime_ffi_delete_peerDevice(lime_manager_t manager, const char *peerDeviceId) { - manager->context->delete_peerDevice(std::string(peerDeviceId)); - return LIME_FFI_SUCCESS; -} - -int lime_ffi_stale_sessions(lime_manager_t manager, const char *localDeviceId, const char *peerDeviceId) { - manager->context->stale_sessions(std::string(localDeviceId), std::string(peerDeviceId)); - return LIME_FFI_SUCCESS; -} - -int lime_ffi_update(lime_manager_t manager, const char *localDeviceId, const lime_ffi_Callback callback, void *callbackUserData, uint16_t OPkServerLowLimit, uint16_t OPkBatchSize) { - // just intercept the lime callback, convert the arguments to the correct types, add the userData and forward it to the C side - limeCallback cb([callback, callbackUserData](const lime::CallbackReturn status, const std::string message){ - callback(callbackUserData, lime2ffi_CallbackReturn(status), message.data()); - }); - - try { - manager->context->update(std::string(localDeviceId), cb, OPkServerLowLimit, OPkBatchSize); - } catch (BctbxException const &e) { - LIME_LOGE<<"FFI failed during update: "<<e.str(); - return LIME_FFI_INTERNAL_ERROR; - } catch (exception const &e) { // catch anything - LIME_LOGE<<"FFI failed during update: "<<e.what(); - return LIME_FFI_INTERNAL_ERROR; - } - return LIME_FFI_SUCCESS; - -} - -int lime_ffi_set_x3dhServerUrl(lime_manager_t manager, const char *localDeviceId, const char *x3dhServerUrl) { - try { - manager->context->set_x3dhServerUrl(std::string(localDeviceId), std::string(x3dhServerUrl)); - } catch (BctbxException const &e) { - LIME_LOGE<<"FFI failed during set X3DH server Url: "<<e.str(); - return LIME_FFI_INTERNAL_ERROR; - } catch (exception const &e) { // catch anything - LIME_LOGE<<"FFI failed during set X3DH server Url: "<<e.what(); - return LIME_FFI_INTERNAL_ERROR; - } - return LIME_FFI_SUCCESS; -} - - -int lime_ffi_get_x3dhServerUrl(lime_manager_t manager, const char *localDeviceId, char *x3dhServerUrl, size_t *x3dhServerUrlSize) { - std::string url{}; - try { - url = manager->context->get_x3dhServerUrl(std::string(localDeviceId)); - } catch (BctbxException const &e) { - LIME_LOGE<<"FFI failed during get X3DH server Url: "<<e.str(); - return LIME_FFI_INTERNAL_ERROR; - } catch (exception const &e) { // catch anything - LIME_LOGE<<"FFI failed during get X3DH server Url: "<<e.what(); - return LIME_FFI_INTERNAL_ERROR; - } - // check the output buffer is large enough - if (url.size() >= *x3dhServerUrlSize) { // >= as we need room for the NULL termination - *x3dhServerUrlSize = 0; - return LIME_FFI_OUTPUT_BUFFER_TOO_SMALL; - } else { - std::copy_n(url.begin(), url.size(), x3dhServerUrl); - x3dhServerUrl[url.size()] = '\0'; - *x3dhServerUrlSize = url.size(); - return LIME_FFI_SUCCESS; - } -} - -} // extern "C" diff --git a/src/lime_jni.cpp b/src/lime_jni.cpp deleted file mode 100644 index 1fe37cd..0000000 --- a/src/lime_jni.cpp +++ /dev/null @@ -1,551 +0,0 @@ -/** - @file lime_jni.cpp - - @author Johan Pascal - - @copyright Copyright (C) 2019 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -#include <jni/jni.hpp> - -#include "lime_log.hpp" -#include <lime/lime.hpp> -#include "bctoolbox/exception.hh" - -/** - * @brief Holds a stateful function pointer to be called to process the X3DH server response - * Encapsulate the function pointer in an object to pass its pointer to the java side - * as it cannot manage stateful function pointers - */ -struct responseHolder { - const lime::limeX3DHServerResponseProcess process; - - responseHolder(const lime::limeX3DHServerResponseProcess &process) : process{process} {}; -}; - - -static void jbyteArray2uin8_tVector(jni::JNIEnv &env, const jni::Array<jni::jbyte> &in, std::shared_ptr<std::vector<uint8_t>> &out) { - // turn the in array into a vector of jbytes(signed char) - std::vector<int8_t> signedResponseVector = jni::Make<std::vector<jbyte>>(env, in); - - // copy it to an unsigned char(not the nost efficient way but c++ seems to be unable to directly cast a vector in a clean way) - for (auto &sb : signedResponseVector) { - out->push_back(reinterpret_cast<uint8_t &>(sb)); - } -} - -/** - * @brief convert an int mapped java enumerated peerDevice Status into a c++ one - * - * mapping is : - * UNTRUSTED(0) TRUSTED(1) UNSAFE(2) FAIL(3) UNKNOWN(4) - * - * @param[in] peerStatus The java mapped integer to a curveId enum - * @return the c++ enumerated peer device status (silently default to unknown) - */ -static lime::PeerDeviceStatus j2cPeerDeviceStatus(jni::jint peerStatus) { - switch (peerStatus) { - case 0: - return lime::PeerDeviceStatus::untrusted; - case 1: - return lime::PeerDeviceStatus::trusted; - case 2: - return lime::PeerDeviceStatus::unsafe; - case 3: - return lime::PeerDeviceStatus::fail; - case 4: - default: - return lime::PeerDeviceStatus::unknown; - } -} - -/** - * @brief convert a c++ enumerated peerDevice Status into a integer one - * - * mapping in java is : - * UNTRUSTED(0) TRUSTED(1) UNSAFE(2) FAIL(3) UNKNOWN(4) - * - * @param[in] peerStatus the c++ enumerated peer Device Status - * @return the java enumerated peer device status (silently default to 4:UNKNOWN) - */ -static jni::jint c2jPeerDeviceStatus(lime::PeerDeviceStatus peerStatus) { - switch (peerStatus) { - case lime::PeerDeviceStatus::untrusted: - return 0; - case lime::PeerDeviceStatus::trusted: - return 1; - case lime::PeerDeviceStatus::unsafe: - return 2; - case lime::PeerDeviceStatus::fail: - return 3; - case lime::PeerDeviceStatus::unknown: - default: - return 4; - } -} - -/** - * @brief convert a c++ enumerated CallbackReturn into a integer one - * - * mapping in java is : - * SUCCESS(0) FAIL(1) - * - * @param[in] status the c++ enumerated peer Device Status - * @return the java enumerated peer device status (silently default to 1:FAIL) - */ -static jni::jint c2jCallbackReturn(lime::CallbackReturn status) { - switch (status) { - case lime::CallbackReturn::success: - return 0; - case lime::CallbackReturn::fail: - default: - return 1; - } -} - -/** - * @brief convert a int mapped java enumerated encryptionPolicy into a c++ one - * - * mapping is : - * DRMESSAGE(0) CIPHERMESSAGE(1) OPTIMIZEUPLOADSIZE(2) OPTIMIZEGLOBALBANDWIDTH(3) - * - * @param[in] encryptionPolicy The java mapped integer to an encryption policy enum - * @return the c++ enumerated encryption policy (silently default to optimizeUploadSize) - */ -static lime::EncryptionPolicy j2cEncryptionPolicy(jni::jint encryptionPolicy) { - switch (encryptionPolicy) { - case 0: - return lime::EncryptionPolicy::DRMessage; - case 1: - return lime::EncryptionPolicy::cipherMessage; - case 3: - return lime::EncryptionPolicy::optimizeGlobalBandwidth; - case 2: - default: - return lime::EncryptionPolicy::optimizeUploadSize; - } -} - -/** - * @brief convert a int mapped java enumerated curveId into a c++ one - * - * mapping is : - * C25519(1) C448(2) - * - * @param[in] curveId The java mapped integer to a curveId enum - * @return the c++ enumerated curveId (silently default to unset) - */ -static lime::CurveId j2cCurveId(jni::jint curveId) { - switch (curveId) { - case 1: - return lime::CurveId::c25519; - case 2: - return lime::CurveId::c448; - default: - return lime::CurveId::unset; - } -} - -extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { - -// java classes we would need to access -struct jPostToX3DH { static constexpr auto Name() { return "org/linphone/lime/LimePostToX3DH"; } }; -struct jStatusCallback { static constexpr auto Name() { return "org/linphone/lime/LimeStatusCallback"; } }; -struct jRecipientData { static constexpr auto Name() { return "org/linphone/lime/RecipientData"; } }; -struct jLimeOutputBuffer { static constexpr auto Name() { return "org/linphone/lime/LimeOutputBuffer"; } }; -struct jLimeException { static constexpr auto Name() { return "org/linphone/lime/LimeException"; } }; - -jni::JNIEnv& env { jni::GetEnv(*vm) }; - - -struct jLimeManager { - static constexpr auto Name() { return "org/linphone/lime/LimeManager"; } // bind this class to the java LimeManager Class - - std::unique_ptr<lime::LimeManager> m_manager; /**< a unique pointer to the actual lime manager */ - jni::Global<jni::Object<jPostToX3DH>, jni::EnvGettingDeleter> jGlobalPostObj; /**< a global reference to the java postToX3DH object. TODO: unclear if EnvIgnoringDeleter is not a better fit here. */ - - inline void ThrowJavaLimeException(JNIEnv& env, const std::string &message) { - auto LimeExceptionClass = env.FindClass("org/linphone/lime/LimeException"); - env.ThrowNew(LimeExceptionClass, message.data()); - } - - /** @brief Constructor - * unlike the native lime manager constructor, this one get only one argument has cpp closure cannot be passed easily to java - * @param[in] db_access the database access path - */ - jLimeManager(JNIEnv &env, const jni::String &db_access, jni::Object<jPostToX3DH> &jpostObj) : jGlobalPostObj{jni::NewGlobal<jni::EnvGettingDeleter>(env, jpostObj)} { - // turn the argument into a cpp string - std::string cpp_db_access = jni::Make<std::string>(env, db_access); - - // retrieve the JavaVM - JavaVM *c_vm; - env.GetJavaVM(&c_vm); - - // closure must capture pointer to current object to be able to access the jGlobalPostObj field - auto thiz = this; - - m_manager = std::make_unique<lime::LimeManager>(cpp_db_access, [c_vm, thiz](const std::string &url, const std::string &from, const std::vector<uint8_t> &message, const lime::limeX3DHServerResponseProcess &responseProcess){ - // (TODO? make sure the current process is attached?) - jni::JNIEnv& g_env { jni::GetEnv(*c_vm)}; - // Create a Cpp object to hold the reponseProcess closure (cannot give a stateful function to the java side) - auto process = new responseHolder(responseProcess); - // retrieve the postToX3DHServer method - auto PostClass = jni::Class<jPostToX3DH>::Find(g_env); - auto PostMethod = PostClass.GetMethod<void (jni::jlong, jni::String, jni::String, jni::Array<jni::jbyte>)>(g_env, "postToX3DHServer"); - - // Call the postToX3DHServer method passing it our pointer holding the response process object - thiz->jGlobalPostObj.Call(g_env, PostMethod, jni::jlong(process), jni::Make<jni::String>(g_env, url), jni::Make<jni::String>(g_env, from), jni::Make<jni::Array<jni::jbyte>>(g_env, reinterpret_cast<const std::vector<int8_t>&>(message))); - }); - } - - jLimeManager(const jLimeManager&) = delete; // noncopyable - - ~jLimeManager() { - // ressources allocated are held by unique ptr, they self delete. - LIME_LOGD<<"JNI destructs native ressources"; - } - - - void create_user(jni::JNIEnv &env, const jni::String &localDeviceId, const jni::String &serverUrl, const jni::jint jcurveId, const jni::jint jOPkInitialBatchSize, jni::Object<jStatusCallback> &jstatusObj ) { - LIME_LOGD<<"JNI create_user user "<<jni::Make<std::string>(env, localDeviceId)<<" url "<<jni::Make<std::string>(env, serverUrl); - JavaVM *c_vm; - env.GetJavaVM(&c_vm); - - // Here we create a global java reference on our object so we won't loose it even if this is called after the current java call - // This global java reference is given in a unique pointer(why??), so just turn it into a shared one so we can copy it into the closure - // We could move it to the closure, but it is itself copied into the create_user argument so it would fail - // Another solution would be to modify the create_user to have it moving the closure and not copying it, it will be used just once anyway - auto jstatusObjRef = std::make_shared<jni::Global<jni::Object<jStatusCallback>, jni::EnvGettingDeleter>>(jni::NewGlobal<jni::EnvGettingDeleter>(env, jstatusObj)); - - auto callback_lambda = [c_vm, jstatusObjRef](const lime::CallbackReturn status, const std::string message){ - // get the env from VM, and retrieve the callback method on StatusCallback class - jni::JNIEnv& g_env { jni::GetEnv(*c_vm)}; - auto StatusClass = jni::Class<jStatusCallback>::Find(g_env); - auto StatusMethod = StatusClass.GetMethod<void (jni::jint, jni::String)>(g_env, "callback"); - // call the callback on the statusObj we got in param when calling create_user - jstatusObjRef->Call(g_env, StatusMethod, c2jCallbackReturn(status), jni::Make<jni::String>(g_env, message)); - }; - - try { - m_manager->create_user( jni::Make<std::string>(env, localDeviceId), - jni::Make<std::string>(env, serverUrl), - j2cCurveId(jcurveId), jOPkInitialBatchSize, callback_lambda); - } catch (BctbxException const &e) { - ThrowJavaLimeException(env, e.str()); - } catch (std::exception const &e) { // catch anything - ThrowJavaLimeException(env, e.what()); - } - } - - void delete_user(jni::JNIEnv &env, const jni::String &localDeviceId, jni::Object<jStatusCallback> &jstatusObj ) { - LIME_LOGD<<"JNI delete_user user "<<jni::Make<std::string>(env, localDeviceId)<<std::endl; - JavaVM *c_vm; - env.GetJavaVM(&c_vm); - - // see create_user for details on this - auto jstatusObjRef = std::make_shared<jni::Global<jni::Object<jStatusCallback>, jni::EnvGettingDeleter>>(jni::NewGlobal<jni::EnvGettingDeleter>(env, jstatusObj)); - - auto callback_lambda = [c_vm, jstatusObjRef](const lime::CallbackReturn status, const std::string message){ - // get the env from VM, and retrieve the callback method on StatusCallback class - jni::JNIEnv& g_env { jni::GetEnv(*c_vm)}; - auto StatusClass = jni::Class<jStatusCallback>::Find(g_env); - auto StatusMethod = StatusClass.GetMethod<void (jni::jint, jni::String)>(g_env, "callback"); - // call the callback on the statusObj we got in param when calling create_user - jstatusObjRef->Call(g_env, StatusMethod, c2jCallbackReturn(status), jni::Make<jni::String>(g_env, message)); - }; - - try { - m_manager->delete_user( jni::Make<std::string>(env, localDeviceId), callback_lambda); - } catch (BctbxException const &e) { - ThrowJavaLimeException(env, e.str()); - } catch (std::exception const &e) { // catch anything - ThrowJavaLimeException(env, e.what()); - } - } - - jni::jboolean is_user(jni::JNIEnv &env, const jni::String &localDeviceId ) { - try { - if (m_manager->is_user(jni::Make<std::string>(env, localDeviceId))) { - return JNI_TRUE; - } else { - return JNI_FALSE; - } - } catch (std::exception const &e) { // catch anything, BctbxException are managed in is_user, so there is a real problem if we get there. - ThrowJavaLimeException(env, e.what()); - return JNI_FALSE; - } - } - - void encrypt(jni::JNIEnv &env, const jni::String &jlocalDeviceId, const jni::String &jrecipientUserId, jni::Array<jni::Object<jRecipientData>> &jrecipients, - jni::Array<jni::jbyte> &jplainMessage, - jni::Object<jLimeOutputBuffer> &jcipherMessage, - jni::Object<jStatusCallback> &jstatusObj, - jni::jint encryptionPolicy) { - - JavaVM *c_vm; - env.GetJavaVM(&c_vm); - - LIME_LOGD<<"JNI Encrypt from "<<(jni::Make<std::string>(env, jlocalDeviceId))<<" to user "<<(jni::Make<std::string>(env, jrecipientUserId))<<" to "<<jrecipients.Length(env)<<" recipients"<<std::endl; - - // turn the plain message byte array into a vector of uint8_t - auto plainMessage = std::make_shared<std::vector<uint8_t>>(); - jbyteArray2uin8_tVector(env, jplainMessage, plainMessage); - - auto cipherMessage = std::make_shared<std::vector<uint8_t>>(); - - // turn the array of jRecipientData into a vector of recipientData - auto recipients = std::make_shared<std::vector<lime::RecipientData>>(); - auto RecipientDataClass = jni::Class<jRecipientData>::Find(env); - auto RecipientDataDeviceIdField = RecipientDataClass.GetField<jni::String>(env, "deviceId"); - auto RecipientDataPeerStatusField = RecipientDataClass.GetField<jni::jint>(env, "peerStatus"); - auto jrecipientsSize = jrecipients.Length(env); - - for (size_t i=0; i<jrecipientsSize; i++) { - auto recipient = jrecipients.Get(env, i); - recipients->emplace_back(jni::Make<std::string>(env, recipient.Get(env, RecipientDataDeviceIdField))); - recipients->back().peerStatus = j2cPeerDeviceStatus(recipient.Get(env, RecipientDataPeerStatusField)); - } - - // we must have shared_pointer for recipientUserId - auto recipientUserId = std::make_shared<std::string>(jni::Make<std::string>(env, jrecipientUserId)); - - // see create_user for details on this - auto jstatusObjRef = std::make_shared<jni::Global<jni::Object<jStatusCallback>, jni::EnvGettingDeleter>>(jni::NewGlobal<jni::EnvGettingDeleter>(env, jstatusObj)); - auto jrecipientsRef = std::make_shared<jni::Global<jni::Array<jni::Object<jRecipientData>>, jni::EnvGettingDeleter>>(jni::NewGlobal<jni::EnvGettingDeleter>(env, jrecipients)); - auto jcipherMessageRef = std::make_shared<jni::Global<jni::Object<jLimeOutputBuffer>, jni::EnvGettingDeleter>>(jni::NewGlobal<jni::EnvGettingDeleter>(env, jcipherMessage)); - - m_manager->encrypt(jni::Make<std::string>(env, jlocalDeviceId), - recipientUserId, - recipients, - plainMessage, - cipherMessage, - [c_vm, jstatusObjRef, jrecipientsRef, jcipherMessageRef, recipients, cipherMessage] (const lime::CallbackReturn status, const std::string message) { - // get the env from VM - jni::JNIEnv& g_env { jni::GetEnv(*c_vm)}; - - // access to java RecipientData fields - auto RecipientDataClass = jni::Class<jRecipientData>::Find(g_env); - auto RecipientDataPeerStatusField = RecipientDataClass.GetField<jni::jint>(g_env, "peerStatus"); - auto RecipientDataDRmessageField = RecipientDataClass.GetField<jni::Array<jni::jbyte>>(g_env, "DRmessage"); - - // retrieve the cpp recipients vector and copy back to the jrecipients the peerStatus and DRmessage(if any) - for (size_t i=0; i<recipients->size(); i++) { - auto jrecipient = jrecipientsRef->Get(g_env, i); // recipient is the recipientData javaObject - jrecipient.Set(g_env, RecipientDataPeerStatusField, c2jPeerDeviceStatus((*recipients)[i].peerStatus)); - auto jDRmessage = jni::Make<jni::Array<jni::jbyte>>(g_env, reinterpret_cast<const std::vector<int8_t>&>((*recipients)[i].DRmessage)); - jrecipient.Set(g_env, RecipientDataDRmessageField, jDRmessage); - } - - // retrieve the LimeOutputBuffer class - auto LimeOutputBufferClass = jni::Class<jLimeOutputBuffer>::Find(g_env); - auto LimeOutputBufferField = LimeOutputBufferClass.GetField<jni::Array<jni::jbyte>>(g_env, "buffer"); - - // get the cipherMessage out - // Can't use directly a byte[] in parameter (as we must create it from c++ code) so use an dedicated class encapsulating a byte[] - auto jcipherMessageArray = jni::Make<jni::Array<jni::jbyte>>(g_env, reinterpret_cast<const std::vector<int8_t>&>(*cipherMessage)); - jcipherMessageRef->Set(g_env, LimeOutputBufferField, jcipherMessageArray); - - // retrieve the callback method on StatusCallback class - auto StatusClass = jni::Class<jStatusCallback>::Find(g_env); - auto StatusMethod = StatusClass.GetMethod<void (jni::jint, jni::String)>(g_env, "callback"); - - // call the callback on the statusObj we got in param when calling create_user - jstatusObjRef->Call(g_env, StatusMethod, c2jCallbackReturn(status), jni::Make<jni::String>(g_env, message)); - }, - j2cEncryptionPolicy(encryptionPolicy) - ); - } - - jni::jint decrypt(jni::JNIEnv &env, const jni::String &jlocalDeviceId, const jni::String &jrecipientUserId, const jni::String &jsenderDeviceId, - jni::Array<jni::jbyte> &jDRmessage, - jni::Array<jni::jbyte> &jcipherMessage, - jni::Object<jLimeOutputBuffer> &jplainMessage) { - - LIME_LOGD<<"JNI Decrypt from "<<(jni::Make<std::string>(env, jsenderDeviceId))<<" for user "<<(jni::Make<std::string>(env, jrecipientUserId))<<" (device : "<<(jni::Make<std::string>(env, jlocalDeviceId))<<")"<<std::endl; - - // turn the DR and cipher message java byte array into a vector of uint8_t - auto DRmessage = std::make_shared<std::vector<uint8_t>>(); - jbyteArray2uin8_tVector(env, jDRmessage, DRmessage); - auto cipherMessage = std::make_shared<std::vector<uint8_t>>(); - jbyteArray2uin8_tVector(env, jcipherMessage, cipherMessage); - - std::vector<uint8_t> plainMessage{}; - - auto status = m_manager->decrypt(jni::Make<std::string>(env, jlocalDeviceId), - jni::Make<std::string>(env, jrecipientUserId), - jni::Make<std::string>(env, jsenderDeviceId), - *DRmessage, - *cipherMessage, - plainMessage); - - // retrieve the LimeOutputBuffer class - auto LimeOutputBufferClass = jni::Class<jLimeOutputBuffer>::Find(env); - auto LimeOutputBufferField = LimeOutputBufferClass.GetField<jni::Array<jni::jbyte>>(env, "buffer"); - - // get the cipherMessage out - // Can't use directly a byte[] in parameter (as we must create it from c++ code) so use an dedicated class encapsulating a byte[] - auto jplainMessageArray = jni::Make<jni::Array<jni::jbyte>>(env, reinterpret_cast<const std::vector<int8_t>&>(plainMessage)); - jplainMessage.Set(env, LimeOutputBufferField, jplainMessageArray); - - return c2jPeerDeviceStatus(status); - } - - void update(jni::JNIEnv &env, const jni::String &jlocalDeviceId, jni::Object<jStatusCallback> &jstatusObj, jni::jint jOPkServerLowLimit, jni::jint jOPkBatchSize) { - JavaVM *c_vm; - env.GetJavaVM(&c_vm); - - LIME_LOGD<<"JNI update for "<<(jni::Make<std::string>(env, jlocalDeviceId)); - - // see create_user for details on this - auto jstatusObjRef = std::make_shared<jni::Global<jni::Object<jStatusCallback>, jni::EnvGettingDeleter>>(jni::NewGlobal<jni::EnvGettingDeleter>(env, jstatusObj)); - - m_manager->update(jni::Make<std::string>(env, jlocalDeviceId), - [c_vm, jstatusObjRef] (const lime::CallbackReturn status, const std::string message) - { - // get the env from VM - jni::JNIEnv& g_env { jni::GetEnv(*c_vm)}; - - // retrieve the callback method on StatusCallback class - auto StatusClass = jni::Class<jStatusCallback>::Find(g_env); - auto StatusMethod = StatusClass.GetMethod<void (jni::jint, jni::String)>(g_env, "callback"); - - // call the callback on the statusObj we got in param when calling create_user - jstatusObjRef->Call(g_env, StatusMethod, c2jCallbackReturn(status), jni::Make<jni::String>(g_env, message)); - }, - jOPkServerLowLimit, jOPkBatchSize); - } - - void get_selfIdentityKey(jni::JNIEnv &env, const jni::String &jlocalDeviceId, jni::Object<jLimeOutputBuffer> &jIk) { - try { - // retrieve the LimeOutputBuffer class - auto LimeOutputBufferClass = jni::Class<jLimeOutputBuffer>::Find(env); - auto LimeOutputBufferField = LimeOutputBufferClass.GetField<jni::Array<jni::jbyte>>(env, "buffer"); - - // get the Ik - std::vector<uint8_t> Ik{}; - m_manager->get_selfIdentityKey(jni::Make<std::string>(env, jlocalDeviceId), Ik); - auto jIkArray = jni::Make<jni::Array<jni::jbyte>>(env, reinterpret_cast<const std::vector<int8_t>&>(Ik)); - jIk.Set(env, LimeOutputBufferField, jIkArray); - } catch (BctbxException const &e) { - ThrowJavaLimeException(env, e.str()); - } catch (std::exception const &e) { // catch anything - ThrowJavaLimeException(env, e.what()); - } - } - - void set_peerDeviceStatus_Ik(jni::JNIEnv &env, const jni::String &jpeerDeviceId, const jni::Array<jni::jbyte> &jIk, const jni::jint jstatus) { - try { - // turn the Ik byte array into a vector of uint8_t - auto Ik = std::make_shared<std::vector<uint8_t>>(); - jbyteArray2uin8_tVector(env, jIk, Ik); - - m_manager->set_peerDeviceStatus(jni::Make<std::string>(env, jpeerDeviceId), *Ik, j2cPeerDeviceStatus(jstatus)); - } catch (BctbxException const &e) { - ThrowJavaLimeException(env, e.str()); - } catch (std::exception const &e) { // catch anything - ThrowJavaLimeException(env, e.what()); - } - } - - void set_peerDeviceStatus(jni::JNIEnv &env, const jni::String &jpeerDeviceId, const jni::jint jstatus) { - m_manager->set_peerDeviceStatus(jni::Make<std::string>(env, jpeerDeviceId), j2cPeerDeviceStatus(jstatus)); - } - - jni::jint get_peerDeviceStatus(jni::JNIEnv &env, const jni::String &jpeerDeviceId) { - return c2jPeerDeviceStatus(m_manager->get_peerDeviceStatus(jni::Make<std::string>(env, jpeerDeviceId))); - } - - void delete_peerDevice(jni::JNIEnv &env, const jni::String &jpeerDeviceId) { - m_manager->delete_peerDevice(jni::Make<std::string>(env, jpeerDeviceId)); - } - - void set_x3dhServerUrl(jni::JNIEnv &env, const jni::String &jlocalDeviceId, const jni::String &jx3dhServerUrl) { - try { - m_manager->set_x3dhServerUrl(jni::Make<std::string>(env, jlocalDeviceId), jni::Make<std::string>(env, jx3dhServerUrl)); - } catch (BctbxException const &e) { - ThrowJavaLimeException(env, e.str()); - } catch (std::exception const &e) { // catch anything - ThrowJavaLimeException(env, e.what()); - } - } - - void stale_sessions(jni::JNIEnv &env, const jni::String &jlocalDeviceId, const jni::String &jpeerDeviceId) { - try { - m_manager->stale_sessions(jni::Make<std::string>(env, jlocalDeviceId), jni::Make<std::string>(env, jpeerDeviceId)); - } catch (BctbxException const &e) { - ThrowJavaLimeException(env, e.str()); - } catch (std::exception const &e) { // catch anything - ThrowJavaLimeException(env, e.what()); - } - } - - - jni::Local<jni::String> get_x3dhServerUrl(jni::JNIEnv &env, const jni::String &jlocalDeviceId) { - std::string url{}; - try { - url = m_manager->get_x3dhServerUrl(jni::Make<std::string>(env, jlocalDeviceId)); - } catch (BctbxException const &e) { - ThrowJavaLimeException(env, e.str()); - } catch (std::exception const &e) { // catch anything - ThrowJavaLimeException(env, e.what()); - } - return jni::Make<jni::String>(env, url); - } -}; - -#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) - -jni::RegisterNativePeer<jLimeManager>(env, jni::Class<jLimeManager>::Find(env), "nativePtr", - jni::MakePeer<jLimeManager, jni::String &, jni::Object<jPostToX3DH> &>, - "initialize", - "nativeDestructor", - METHOD(&jLimeManager::create_user, "n_create_user"), - METHOD(&jLimeManager::delete_user, "delete_user"), - METHOD(&jLimeManager::is_user, "is_user"), - METHOD(&jLimeManager::encrypt, "n_encrypt"), - METHOD(&jLimeManager::decrypt, "n_decrypt"), - METHOD(&jLimeManager::update, "n_update"), - METHOD(&jLimeManager::get_selfIdentityKey, "get_selfIdentityKey"), - METHOD(&jLimeManager::set_peerDeviceStatus_Ik, "n_set_peerDeviceStatus_Ik"), - METHOD(&jLimeManager::set_peerDeviceStatus, "n_set_peerDeviceStatus"), - METHOD(&jLimeManager::get_peerDeviceStatus, "n_get_peerDeviceStatus"), - METHOD(&jLimeManager::delete_peerDevice, "delete_peerDevice"), - METHOD(&jLimeManager::set_x3dhServerUrl, "set_x3dhServerUrl"), - METHOD(&jLimeManager::get_x3dhServerUrl, "get_x3dhServerUrl") - ); - -// bind the process_response to the static java LimeManager.process_response method -// This is not done in the previous RegisterNativePeer because the method is static -/** - * @brief process response from X3DH server - * This function is bind to a java PostToX3DH object process_response method - * It : - * - converts from jbytes(signed char) to unsigned char the response array - * - retrieves from the given back responseHolder pointer the closure pointer to callback the line lib and call it - */ -auto process_X3DHresponse= [](jni::JNIEnv &env, jni::Class<jLimeManager>&, jni::jlong processPtr, jni::jint responseCode, jni::Array<jni::jbyte> &response) { - // turn the response array into a vector of jbytes(signed char) - auto responseVector = std::make_shared<std::vector<uint8_t>>(); - jbyteArray2uin8_tVector(env, response, responseVector); - // retrieve the statefull closure pointer to response processing provided by the lime lib - auto responseHolderPtr = reinterpret_cast<responseHolder *>(processPtr); - responseHolderPtr->process(responseCode, *responseVector); - delete(responseHolderPtr); - }; - -jni::RegisterNatives(env, *jni::Class<jLimeManager>::Find(env), jni::MakeNativeMethod("process_X3DHresponse", process_X3DHresponse)); - -return jni::Unwrap(jni::jni_version_1_2); -} // JNI_OnLoad -- GitLab