diff --git a/BOB.cpp b/BOB.cpp index 15b7066b..72cbcd16 100644 --- a/BOB.cpp +++ b/BOB.cpp @@ -430,8 +430,10 @@ namespace client void BOBCommandSession::SetkeysCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: setkeys ", operand); - m_Keys.FromBase64 (operand); - SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ()); + if (m_Keys.FromBase64 (operand)) + SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ()); + else + SendReplyError ("invalid keys"); } void BOBCommandSession::GetkeysCommandHandler (const char * operand, size_t len) diff --git a/Config.cpp b/Config.cpp index 963ac755..7dada817 100644 --- a/Config.cpp +++ b/Config.cpp @@ -238,18 +238,26 @@ namespace config { ; } - void ParseCmdline(int argc, char* argv[]) { - try { + void ParseCmdline(int argc, char* argv[], bool ignoreUnknown) + { + try + { auto style = boost::program_options::command_line_style::unix_style | boost::program_options::command_line_style::allow_long_disguise; style &= ~ boost::program_options::command_line_style::allow_guessing; - store(parse_command_line(argc, argv, m_OptionsDesc, style), m_Options); - } catch (boost::program_options::error& e) { + if (ignoreUnknown) + store(command_line_parser(argc, argv).options(m_OptionsDesc).style (style).allow_unregistered().run(), m_Options); + else + store(parse_command_line(argc, argv, m_OptionsDesc, style), m_Options); + } + catch (boost::program_options::error& e) + { std::cerr << "args: " << e.what() << std::endl; exit(EXIT_FAILURE); } - if (m_Options.count("help") || m_Options.count("h")) { + if (!ignoreUnknown && (m_Options.count("help") || m_Options.count("h"))) + { std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl; std::cout << m_OptionsDesc; exit(EXIT_SUCCESS); diff --git a/Config.h b/Config.h index 595331cd..1895da55 100644 --- a/Config.h +++ b/Config.h @@ -41,7 +41,7 @@ namespace config { * * Other exceptions will be passed to higher level. */ - void ParseCmdline(int argc, char* argv[]); + void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false); /** * @brief Load and parse given config file diff --git a/Crypto.cpp b/Crypto.cpp index 9e328fd0..0ac65671 100644 --- a/Crypto.cpp +++ b/Crypto.cpp @@ -799,7 +799,7 @@ namespace crypto }*/ - void InitCrypto (bool precomputation, bool withGost) + void InitCrypto (bool precomputation) { SSL_library_init (); /* auto numLocks = CRYPTO_num_locks(); diff --git a/Crypto.h b/Crypto.h index f55e1bd7..16a4da3c 100644 --- a/Crypto.h +++ b/Crypto.h @@ -279,7 +279,7 @@ namespace crypto #endif }; - void InitCrypto (bool precomputation, bool withGost = false); + void InitCrypto (bool precomputation); void TerminateCrypto (); } } diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index 416b6d2c..f282f2d4 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -42,6 +42,9 @@ void handle_signal(int sig) case SIGTERM: Daemon.running = 0; // Exit loop break; + case SIGPIPE: + LogPrint(eLogInfo, "SIGPIPE received"); + break; } } @@ -160,6 +163,7 @@ namespace i2p sigaction(SIGABRT, &sa, 0); sigaction(SIGTERM, &sa, 0); sigaction(SIGINT, &sa, 0); + sigaction(SIGPIPE, &sa, 0); return Daemon_Singleton::start(); } diff --git a/Gost.cpp b/Gost.cpp index 41f52b7c..ba34c66c 100644 --- a/Gost.cpp +++ b/Gost.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "I2PEndian.h" #include "Gost.h" namespace i2p @@ -95,6 +96,38 @@ namespace crypto return ret; } + EC_POINT * GOSTR3410Curve::RecoverPublicKey (const BIGNUM * digest, const BIGNUM * r, const BIGNUM * s, bool isNegativeY) const + { + // s*P = r*Q + h*C + BN_CTX * ctx = BN_CTX_new (); + BN_CTX_start (ctx); + EC_POINT * C = EC_POINT_new (m_Group); // C = k*P = (rx, ry) + EC_POINT * Q = nullptr; + if (EC_POINT_set_compressed_coordinates_GFp (m_Group, C, r, isNegativeY ? 1 : 0, ctx)) + { + EC_POINT * S = EC_POINT_new (m_Group); // S = s*P + EC_POINT_mul (m_Group, S, s, nullptr, nullptr, ctx); + BIGNUM * q = BN_CTX_get (ctx); + EC_GROUP_get_order(m_Group, q, ctx); + BIGNUM * h = BN_CTX_get (ctx); + BN_mod (h, digest, q, ctx); // h = digest % q + BN_sub (h, q, h); // h = -h + EC_POINT * H = EC_POINT_new (m_Group); + EC_POINT_mul (m_Group, H, nullptr, C, h, ctx); // -h*C + EC_POINT_add (m_Group, C, S, H, ctx); // s*P - h*C + EC_POINT_free (H); + EC_POINT_free (S); + BIGNUM * r1 = BN_CTX_get (ctx); + BN_mod_inverse (r1, r, q, ctx); + Q = EC_POINT_new (m_Group); + EC_POINT_mul (m_Group, Q, nullptr, C, r1, ctx); // (s*P - h*C)/r + } + EC_POINT_free (C); + BN_CTX_end (ctx); + BN_CTX_free (ctx); + return Q; + } + static GOSTR3410Curve * CreateGOSTR3410Curve (GOSTR3410ParamSet paramSet) { // a, b, p, q, x, y @@ -107,15 +140,7 @@ namespace crypto "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893", "1", "8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14" - }, // A - { - "C2173F1513981673AF4892C23035A27CE25E2013BF95AA33B22C656F277E7335", - "295F9BAE7428ED9CCC20E7C359A9D41A22FCCD9108E17BF7BA9337A6F8AE9513", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97", - "400000000000000000000000000000000FD8CDDFC87B6635C115AF556C360C67", - "0D", - "32879423AB1A0375895786C4BB46E9565FDE0B5344766740AF268ADB32322E5C" - }, // tc26-2012-paramSetA-256 + }, // CryptoPro A { "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4", "E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760", @@ -192,20 +217,7 @@ namespace crypto 0x492c024284fbaec0, 0xaa16012142f35760, 0x550b8e9e21f7a530, 0xa48b474f9ef5dc18, 0x70a6a56e2440598e, 0x3853dc371220a247, 0x1ca76e95091051ad, 0x0edd37c48a08a6d8, 0x07e095624504536c, 0x8d70c431ac02a736, 0xc83862965601dd1b, 0x641c314b2b8ee083 - }; - - static const uint8_t T_[64]= - { - 0, 8, 16, 24, 32, 40, 48, 56, - 1, 9, 17, 25, 33, 41, 49, 57, - 2, 10, 18, 26, 34, 42, 50, 58, - 3, 11, 19, 27, 35, 43, 51, 59, - 4, 12, 20, 28, 36, 44, 52, 60, - 5, 13, 21, 29, 37, 45, 53, 61, - 6, 14, 22, 30, 38, 46, 54, 62, - 7, 15, 23, 31, 39, 47, 55, 63 - }; - + }; static const uint8_t C_[12][64] = { @@ -327,51 +339,36 @@ namespace crypto } } - void S () - { - for (int i = 0; i < 64; i++) - buf[i] = sbox_[buf[i]]; - } - - void L () + void SPL () { + uint8_t p[64]; + memcpy (p, buf, 64); // we need to copy it for P's transposition for (int i = 0; i < 8; i++) { uint64_t c = 0; for (int j = 0; j < 8; j++) { uint8_t bit = 0x80; + uint8_t byte = sbox_[p[j*8+i]]; // S - sbox_, P - transpose (i,j) for (int k = 0; k < 8; k++) { - if (buf[i*8+j] & bit) c ^= A_[j*8+k]; + if (byte & bit) c ^= A_[j*8+k]; bit >>= 1; } } - ll[i] = c; + ll[i] = htobe64 (c); } } - void P () - { - uint8_t t[64]; - for (int i = 0; i < 64; i++) - t[i] = buf[T_[i]]; - memcpy (buf, t, 64); - } - GOST3411Block E (const GOST3411Block& m) { GOST3411Block k = *this; GOST3411Block res = k^m; for (int i = 0; i < 12; i++) { - res.S (); - res.P (); - res.L (); + res.SPL (); k = k^C_[i]; - k.S (); - k.P (); - k.L (); + k.SPL (); res = k^res; } return res; @@ -381,12 +378,10 @@ namespace crypto static GOST3411Block gN (const GOST3411Block& N, const GOST3411Block& h, const GOST3411Block& m) { GOST3411Block res = N ^ h; - res.S (); - res.P (); - res.L (); + res.SPL (); res = res.E (m); - res = res ^ h; - res = res ^ m; + res = res^h; + res = res^m; return res; } @@ -405,7 +400,7 @@ namespace crypto h= gN (N, h, m); N.Add (512); s = m + s; - len -= 64; + l -= 64; } // stage 3 size_t padding = 64 - l; diff --git a/Gost.h b/Gost.h index 9b65fcf1..4790f696 100644 --- a/Gost.h +++ b/Gost.h @@ -13,13 +13,10 @@ namespace crypto enum GOSTR3410ParamSet { - // GOST R 34.10-2001 eGOSTR3410CryptoProA = 0, // 1.2.643.2.2.35.1 // XchA = A, XchB = C //eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0 - //eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1 - // GOST R 34.10-2012 - eGOSTR3410TC26A256, // 1.2.643.7.1.2.1.1.1 + //eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1 eGOSTR3410TC26A512, // 1.2.643.7.1.2.1.2.1 eGOSTR3410NumParamSets }; @@ -32,11 +29,13 @@ namespace crypto ~GOSTR3410Curve (); size_t GetKeyLen () const { return m_KeyLen; }; + const EC_GROUP * GetGroup () const { return m_Group; }; EC_POINT * MulP (const BIGNUM * n) const; bool GetXY (const EC_POINT * p, BIGNUM * x, BIGNUM * y) const; EC_POINT * CreatePoint (const BIGNUM * x, const BIGNUM * y) const; void Sign (const BIGNUM * priv, const BIGNUM * digest, BIGNUM * r, BIGNUM * s); bool Verify (const EC_POINT * pub, const BIGNUM * digest, const BIGNUM * r, const BIGNUM * s); + EC_POINT * RecoverPublicKey (const BIGNUM * digest, const BIGNUM * r, const BIGNUM * s, bool isNegativeY = false) const; private: @@ -47,7 +46,7 @@ namespace crypto std::unique_ptr& GetGOSTR3410Curve (GOSTR3410ParamSet paramSet); void GOSTR3411_2012_256 (const uint8_t * buf, size_t len, uint8_t * digest); - void GOSTR3411_2012_512 (const uint8_t * buf, size_t len, uint8_t * digest); + void GOSTR3411_2012_512 (const uint8_t * buf, size_t len, uint8_t * digest); } } diff --git a/Identity.cpp b/Identity.cpp index b5b72c43..4f48ae31 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -102,8 +102,8 @@ namespace data memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH); break; } - case SIGNING_KEY_TYPE_GOSTR3410_2001_CRYPTO_PRO_A_GOSTR3411: - case SIGNING_KEY_TYPE_GOSTR3410_2012_TC26_A_256_GOSTR3411: + case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256: + case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST: { // 256 size_t padding = 128 - i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH; // 64 = 128 - 64 @@ -111,7 +111,8 @@ namespace data memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH); break; } - case SIGNING_KEY_TYPE_GOSTR3410_2012_TC26_A_512_GOSTR3411: + case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512: + case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST: { // 512 // no padding, key length is 128 @@ -386,22 +387,18 @@ namespace data UpdateVerifier (new i2p::crypto::EDDSA25519Verifier (m_StandardIdentity.signingKey + padding)); break; } - case SIGNING_KEY_TYPE_GOSTR3410_2001_CRYPTO_PRO_A_GOSTR3411: + case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256: + case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST: { size_t padding = 128 - i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH; // 64 = 128 - 64 - UpdateVerifier (new i2p::crypto::GOSTR3410_2001_Verifier (i2p::crypto::eGOSTR3410CryptoProA, m_StandardIdentity.signingKey + padding)); - break; - } - case SIGNING_KEY_TYPE_GOSTR3410_2012_TC26_A_256_GOSTR3411: - { - size_t padding = 128 - i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH; // 64 = 128 - 64 - UpdateVerifier (new i2p::crypto::GOSTR3410_2012_256_Verifier (i2p::crypto::eGOSTR3410TC26A256, m_StandardIdentity.signingKey + padding)); + UpdateVerifier (new i2p::crypto::GOSTR3410_256_Verifier (i2p::crypto::eGOSTR3410CryptoProA, m_StandardIdentity.signingKey + padding)); break; } - case SIGNING_KEY_TYPE_GOSTR3410_2012_TC26_A_512_GOSTR3411: + case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512: + case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST: { // zero padding - UpdateVerifier (new i2p::crypto::GOSTR3410_2012_512_Verifier (i2p::crypto::eGOSTR3410TC26A512, m_StandardIdentity.signingKey)); + UpdateVerifier (new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512, m_StandardIdentity.signingKey)); break; } default: @@ -462,8 +459,9 @@ namespace data size_t PrivateKeys::FromBuffer (const uint8_t * buf, size_t len) { - m_Public = std::make_shared(buf, len); - size_t ret = m_Public->GetFullLen (); + m_Public = std::make_shared(); + size_t ret = m_Public->FromBuffer (buf, len); + if (!ret || ret + 256 > len) return 0; // overflow memcpy (m_PrivateKey, buf + ret, 256); // private key always 256 ret += 256; size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); @@ -545,14 +543,13 @@ namespace data case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH)); break; - case SIGNING_KEY_TYPE_GOSTR3410_2001_CRYPTO_PRO_A_GOSTR3411: - m_Signer.reset (new i2p::crypto::GOSTR3410_2001_Signer (i2p::crypto::eGOSTR3410CryptoProA, m_SigningPrivateKey)); - break; - case SIGNING_KEY_TYPE_GOSTR3410_2012_TC26_A_256_GOSTR3411: - m_Signer.reset (new i2p::crypto::GOSTR3410_2012_256_Signer (i2p::crypto::eGOSTR3410TC26A256, m_SigningPrivateKey)); + case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256: + case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST: + m_Signer.reset (new i2p::crypto::GOSTR3410_256_Signer (i2p::crypto::eGOSTR3410CryptoProA, m_SigningPrivateKey)); break; - case SIGNING_KEY_TYPE_GOSTR3410_2012_TC26_A_512_GOSTR3411: - m_Signer.reset (new i2p::crypto::GOSTR3410_2012_512_Signer (i2p::crypto::eGOSTR3410TC26A512, m_SigningPrivateKey)); + case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512: + case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST: + m_Signer.reset (new i2p::crypto::GOSTR3410_512_Signer (i2p::crypto::eGOSTR3410TC26A512, m_SigningPrivateKey)); break; default: LogPrint (eLogError, "Identity: Signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported"); @@ -588,14 +585,13 @@ namespace data break; case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); - break; - case SIGNING_KEY_TYPE_GOSTR3410_2001_CRYPTO_PRO_A_GOSTR3411: - i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410CryptoProA, keys.m_SigningPrivateKey, signingPublicKey); break; - case SIGNING_KEY_TYPE_GOSTR3410_2012_TC26_A_256_GOSTR3411: - i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A256, keys.m_SigningPrivateKey, signingPublicKey); + case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256: + case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST: + i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410CryptoProA, keys.m_SigningPrivateKey, signingPublicKey); break; - case SIGNING_KEY_TYPE_GOSTR3410_2012_TC26_A_512_GOSTR3411: + case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512: + case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST: i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, keys.m_SigningPrivateKey, signingPublicKey); break; default: diff --git a/Identity.h b/Identity.h index 1c3c8c18..6c00586b 100644 --- a/Identity.h +++ b/Identity.h @@ -60,11 +60,14 @@ namespace data const uint16_t SIGNING_KEY_TYPE_RSA_SHA384_3072 = 5; const uint16_t SIGNING_KEY_TYPE_RSA_SHA512_4096 = 6; const uint16_t SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 = 7; + const uint16_t SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519ph = 8; // not implemented // following signature type should never appear in netid=2 - const uint16_t SIGNING_KEY_TYPE_GOSTR3410_2001_CRYPTO_PRO_A_GOSTR3411 = 65280; // approved by FSB - const uint16_t SIGNING_KEY_TYPE_GOSTR3410_2012_TC26_A_256_GOSTR3411 = 65281; - const uint16_t SIGNING_KEY_TYPE_GOSTR3410_2012_TC26_A_512_GOSTR3411 = 65282; - + const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256 = 9; + const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512 = 10; // approved by FSB + // TODO: remove later + const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST = 65281; + const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST = 65282; + typedef uint16_t SigningKeyType; typedef uint16_t CryptoKeyType; diff --git a/Makefile.linux b/Makefile.linux index af23f955..c4d78447 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -55,15 +55,12 @@ else endif endif -IS_64 := $(shell $(CXX) -dumpmachine 2>&1 | $(GREP) -c "64") ifeq ($(USE_AESNI),yes) -ifeq ($(IS_64),1) #check if AES-NI is supported by CPU ifneq ($(shell $(GREP) -c aes /proc/cpuinfo),0) CPU_FLAGS += -maes -DAESNI endif endif -endif ifeq ($(USE_AVX),yes) #check if AVX supported by CPU diff --git a/SAM.cpp b/SAM.cpp index d89750f2..42968c7a 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -18,7 +18,7 @@ namespace client SAMSocket::SAMSocket (SAMBridge& owner): m_Owner (owner), m_Socket (m_Owner.GetService ()), m_Timer (m_Owner.GetService ()), m_BufferOffset (0), m_SocketType (eSAMSocketTypeUnknown), m_IsSilent (false), - m_Stream (nullptr), m_Session (nullptr) + m_IsAccepting (false), m_Stream (nullptr), m_Session (nullptr) { } @@ -56,7 +56,7 @@ namespace client if (m_Session) { m_Session->DelSocket (shared_from_this ()); - if (m_Session->localDestination) + if (m_IsAccepting && m_Session->localDestination) m_Session->localDestination->StopAcceptingStreams (); } break; @@ -214,11 +214,11 @@ namespace client if (!strcmp (m_Buffer, SAM_SESSION_CREATE)) ProcessSessionCreate (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_STREAM_CONNECT)) - ProcessStreamConnect (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); + ProcessStreamConnect (separator + 1, bytes_transferred - (separator - m_Buffer) - 1, bytes_transferred - (eol - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_STREAM_ACCEPT)) ProcessStreamAccept (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_DEST_GENERATE)) - ProcessDestGenerate (); + ProcessDestGenerate (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_NAMING_LOOKUP)) ProcessNamingLookup (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_DATAGRAM_SEND)) @@ -358,7 +358,7 @@ namespace client SendMessageReply (m_Buffer, l2, false); } - void SAMSocket::ProcessStreamConnect (char * buf, size_t len) + void SAMSocket::ProcessStreamConnect (char * buf, size_t len, size_t rem) { LogPrint (eLogDebug, "SAM: stream connect: ", buf); std::map params; @@ -371,9 +371,17 @@ namespace client m_Session = m_Owner.FindSession (id); if (m_Session) { + if (rem > 0) // handle follow on data + { + memmove (m_Buffer, buf + len + 1, rem); // buf is a pointer to m_Buffer's content + m_BufferOffset = rem; + } + else + m_BufferOffset = 0; + auto dest = std::make_shared (); - size_t len = dest->FromBase64(destination); - if (len > 0) + size_t l = dest->FromBase64(destination); + if (l > 0) { context.GetAddressBook().InsertAddress(dest); auto leaseSet = m_Session->localDestination->FindLeaseSet(dest->GetIdentHash()); @@ -398,7 +406,8 @@ namespace client m_SocketType = eSAMSocketTypeStream; m_Session->AddSocket (shared_from_this ()); m_Stream = m_Session->localDestination->CreateStream (remote); - m_Stream->Send ((uint8_t *)m_Buffer, 0); // connect + m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send + m_BufferOffset = 0; I2PReceive (); SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); } @@ -429,7 +438,10 @@ namespace client m_SocketType = eSAMSocketTypeAcceptor; m_Session->AddSocket (shared_from_this ()); if (!m_Session->localDestination->IsAcceptingStreams ()) + { + m_IsAccepting = true; m_Session->localDestination->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); + } SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); } else @@ -467,18 +479,26 @@ namespace client return offset + size; } - void SAMSocket::ProcessDestGenerate () + void SAMSocket::ProcessDestGenerate (char * buf, size_t len) { LogPrint (eLogDebug, "SAM: dest generate"); - auto keys = i2p::data::PrivateKeys::CreateRandomKeys (); + std::map params; + ExtractParams (buf, params); + // extract signature type + i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; + auto it = params.find (SAM_PARAM_SIGNATURE_TYPE); + if (it != params.end ()) + // TODO: extract string values + signatureType = std::stoi(it->second); + auto keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType); #ifdef _MSC_VER - size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, + size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ()); #else - size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, + size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ()); #endif - SendMessageReply (m_Buffer, len, false); + SendMessageReply (m_Buffer, l, false); } void SAMSocket::ProcessNamingLookup (char * buf, size_t len) @@ -603,6 +623,8 @@ namespace client { if (m_Stream) { + bytes_transferred += m_BufferOffset; + m_BufferOffset = 0; auto s = shared_from_this (); m_Stream->AsyncSend ((uint8_t *)m_Buffer, bytes_transferred, [s](const boost::system::error_code& ecode) @@ -690,6 +712,7 @@ namespace client { LogPrint (eLogDebug, "SAM: incoming I2P connection for session ", m_ID); m_SocketType = eSAMSocketTypeStream; + m_IsAccepting = false; m_Stream = stream; context.GetAddressBook ().InsertAddress (stream->GetRemoteIdentity ()); auto session = m_Owner.FindSession (m_ID); @@ -699,6 +722,7 @@ namespace client for (auto it: session->ListSockets ()) if (it->m_SocketType == eSAMSocketTypeAcceptor) { + it->m_IsAccepting = true; session->localDestination->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, it, std::placeholders::_1)); break; } @@ -778,13 +802,14 @@ namespace client void SAMSession::CloseStreams () { + std::vector > socks; { std::lock_guard lock(m_SocketsMutex); - for (auto& sock : m_Sockets) { - sock->CloseStream(); + for (const auto& sock : m_Sockets) { + socks.push_back(sock); } } - // XXX: should this be done inside locked parts? + for (auto & sock : socks ) sock->Terminate(); m_Sockets.clear(); } @@ -875,7 +900,7 @@ namespace client if (destination != "") { i2p::data::PrivateKeys keys; - keys.FromBase64 (destination); + if (!keys.FromBase64 (destination)) return nullptr; localDestination = i2p::client::context.CreateNewLocalDestination (keys, true, params); } else // transient diff --git a/SAM.h b/SAM.h index db6991f5..d8a6ca1a 100644 --- a/SAM.h +++ b/SAM.h @@ -87,9 +87,9 @@ namespace client void SetSocketType (SAMSocketType socketType) { m_SocketType = socketType; }; SAMSocketType GetSocketType () const { return m_SocketType; }; + void Terminate (); private: - void Terminate (); void HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleHandshakeReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleMessage (const boost::system::error_code& ecode, std::size_t bytes_transferred); @@ -105,9 +105,9 @@ namespace client void HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void ProcessSessionCreate (char * buf, size_t len); - void ProcessStreamConnect (char * buf, size_t len); + void ProcessStreamConnect (char * buf, size_t len, size_t rem); void ProcessStreamAccept (char * buf, size_t len); - void ProcessDestGenerate (); + void ProcessDestGenerate (char * buf, size_t len); void ProcessNamingLookup (char * buf, size_t len); void SendI2PError(const std::string & msg); size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0 @@ -131,6 +131,7 @@ namespace client SAMSocketType m_SocketType; std::string m_ID; // nickname bool m_IsSilent; + bool m_IsAccepting; // for eSAMSocketTypeAcceptor only std::shared_ptr m_Stream; std::shared_ptr m_Session; }; @@ -143,13 +144,13 @@ namespace client std::mutex m_SocketsMutex; /** safely add a socket to this session */ - void AddSocket(std::shared_ptr sock) { + void AddSocket(const std::shared_ptr & sock) { std::lock_guard lock(m_SocketsMutex); m_Sockets.push_back(sock); } /** safely remove a socket from this session */ - void DelSocket(std::shared_ptr sock) { + void DelSocket(const std::shared_ptr & sock) { std::lock_guard lock(m_SocketsMutex); m_Sockets.remove(sock); } diff --git a/Signature.cpp b/Signature.cpp index 7571760a..12ee6c2c 100644 --- a/Signature.cpp +++ b/Signature.cpp @@ -168,14 +168,13 @@ namespace crypto BN_mul (x3, p1.x, p2.x, ctx); // A = x1*x2 BN_mul (y3, p1.y, p2.y, ctx); // B = y1*y2 - + + BN_CTX_start (ctx); BIGNUM * t1 = p1.t, * t2 = p2.t; - if (!t1) { t1 = BN_new (); BN_mul (t1, p1.x, p1.y, ctx); } - if (!t2) { t2 = BN_new (); BN_mul (t2, p2.x, p2.y, ctx); } + if (!t1) { t1 = BN_CTX_get (ctx); BN_mul (t1, p1.x, p1.y, ctx); } + if (!t2) { t2 = BN_CTX_get (ctx); BN_mul (t2, p2.x, p2.y, ctx); } BN_mul (t3, t1, t2, ctx); BN_mul (t3, t3, d, ctx); // C = d*t1*t2 - if (!p1.t) BN_free (t1); - if (!p2.t) BN_free (t2); if (p1.z) { @@ -192,7 +191,6 @@ namespace crypto BN_one (z3); // D = 1 } - BN_CTX_start (ctx); BIGNUM * E = BN_CTX_get (ctx), * F = BN_CTX_get (ctx), * G = BN_CTX_get (ctx), * H = BN_CTX_get (ctx); BN_add (E, p1.x, p1.y); BN_add (F, p2.x, p2.y); @@ -213,9 +211,10 @@ namespace crypto return EDDSAPoint {x3, y3, z3, t3}; } - EDDSAPoint Double (const EDDSAPoint& p, BN_CTX * ctx) const + void Double (EDDSAPoint& p, BN_CTX * ctx) const { - BIGNUM * x2 = BN_new (), * y2 = BN_new (), * z2 = BN_new (), * t2 = BN_new (); + BN_CTX_start (ctx); + BIGNUM * x2 = BN_CTX_get (ctx), * y2 = BN_CTX_get (ctx), * z2 = BN_CTX_get (ctx), * t2 = BN_CTX_get (ctx); BN_sqr (x2, p.x, ctx); // x2 = A = x^2 BN_sqr (y2, p.y, ctx); // y2 = B = y^2 @@ -232,7 +231,6 @@ namespace crypto else BN_one (z2); // z2 = 1 - BN_CTX_start (ctx); BIGNUM * E = BN_CTX_get (ctx), * F = BN_CTX_get (ctx), * G = BN_CTX_get (ctx), * H = BN_CTX_get (ctx); // E = (x+y)*(x+y)-A-B = x^2+y^2+2xy-A-B = 2xy BN_mul (E, p.x, p.y, ctx); @@ -241,14 +239,14 @@ namespace crypto BN_add (G, z2, t2); // G = D + C BN_add (H, y2, x2); // H = B + A - BN_mod_mul (x2, E, F, q, ctx); // x2 = E*F - BN_mod_mul (y2, G, H, q, ctx); // y2 = G*H - BN_mod_mul (z2, F, G, q, ctx); // z2 = F*G - BN_mod_mul (t2, E, H, q, ctx); // t2 = E*H + BN_mod_mul (p.x, E, F, q, ctx); // x2 = E*F + BN_mod_mul (p.y, G, H, q, ctx); // y2 = G*H + if (!p.z) p.z = BN_new (); + BN_mod_mul (p.z, F, G, q, ctx); // z2 = F*G + if (!p.t) p.t = BN_new (); + BN_mod_mul (p.t, E, H, q, ctx); // t2 = E*H BN_CTX_end (ctx); - - return EDDSAPoint {x2, y2, z2, t2}; } EDDSAPoint Mul (const EDDSAPoint& p, const BIGNUM * e, BN_CTX * ctx) const @@ -261,7 +259,7 @@ namespace crypto int bitCount = BN_num_bits (e); for (int i = bitCount - 1; i >= 0; i--) { - res = Double (res, ctx); + Double (res, ctx); if (BN_is_bit_set (e, i)) res = Sum (res, p, ctx); } } diff --git a/Signature.h b/Signature.h index aee8c487..b85ef4cf 100644 --- a/Signature.h +++ b/Signature.h @@ -444,32 +444,22 @@ namespace crypto } - // ГОСТ Р 34.11 - struct GOSTR3411_2001_Hash + // ГОСТ Р 34.11 + struct GOSTR3411_256_Hash { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { - SHA256 (buf, len, digest); // TODO: implement GOST R 34.11 - 2001 - } - - enum { hashLen = 32 }; - }; - - struct GOSTR3411_2012_256_Hash - { - static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) - { - SHA256 (buf, len, digest); // TODO: implement GOST R 34.11 - 2012 + GOSTR3411_2012_256 (buf, len, digest); } enum { hashLen = 32 }; }; - struct GOSTR3411_2012_512_Hash + struct GOSTR3411_512_Hash { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { - SHA512 (buf, len, digest); // TODO: implement GOST R 34.11 - 2012 + GOSTR3411_2012_512 (buf, len, digest); } enum { hashLen = 64 }; @@ -566,12 +556,10 @@ namespace crypto BN_free (x); BN_free (y); } - typedef GOSTR3410Verifier GOSTR3410_2001_Verifier; - typedef GOSTR3410Signer GOSTR3410_2001_Signer; - typedef GOSTR3410Verifier GOSTR3410_2012_256_Verifier; - typedef GOSTR3410Signer GOSTR3410_2012_256_Signer; - typedef GOSTR3410Verifier GOSTR3410_2012_512_Verifier; - typedef GOSTR3410Signer GOSTR3410_2012_512_Signer; + typedef GOSTR3410Verifier GOSTR3410_256_Verifier; + typedef GOSTR3410Signer GOSTR3410_256_Signer; + typedef GOSTR3410Verifier GOSTR3410_512_Verifier; + typedef GOSTR3410Signer GOSTR3410_512_Signer; } } diff --git a/Streaming.cpp b/Streaming.cpp index 0045b10d..db5f825e 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -1091,16 +1091,18 @@ namespace stream } else // we must save old acceptor and set it back { - auto oldAcceptor = m_Acceptor; - m_Acceptor = [acceptor, oldAcceptor, this](std::shared_ptr stream) - { - acceptor (stream); - m_Acceptor = oldAcceptor; - }; + m_Acceptor = std::bind (&StreamingDestination::AcceptOnceAcceptor, this, + std::placeholders::_1, acceptor, m_Acceptor); } }); } + void StreamingDestination::AcceptOnceAcceptor (std::shared_ptr stream, Acceptor acceptor, Acceptor prev) + { + m_Acceptor = prev; + acceptor (stream); + } + void StreamingDestination::HandlePendingIncomingTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) diff --git a/Streaming.h b/Streaming.h index be8f3f1a..c598245a 100644 --- a/Streaming.h +++ b/Streaming.h @@ -280,7 +280,9 @@ namespace stream void DeletePacket (Packet * p) { if (p) m_PacketsPool.Release (p); }; private: - + + void AcceptOnceAcceptor (std::shared_ptr stream, Acceptor acceptor, Acceptor prev); + void HandleNextPacket (Packet * packet); std::shared_ptr CreateNewIncomingStream (); void HandlePendingIncomingTimer (const boost::system::error_code& ecode); diff --git a/api.cpp b/api.cpp index ec109439..ffc2de6e 100644 --- a/api.cpp +++ b/api.cpp @@ -19,7 +19,7 @@ namespace api void InitI2P (int argc, char* argv[], const char * appName) { i2p::config::Init (); - i2p::config::ParseCmdline (argc, argv); + i2p::config::ParseCmdline (argc, argv, true); // ignore unknown options and help i2p::config::Finalize (); std::string datadir; i2p::config::GetOption("datadir", datadir); diff --git a/appveyor.yml b/appveyor.yml index 0018d85a..e55edf39 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,6 +19,7 @@ environment: install: - c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc" - c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu" + - c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu" - if "%MSYSTEM%" == "MINGW64" ( diff --git a/build/.gitignore b/build/.gitignore index 79c3f959..e420022a 100644 --- a/build/.gitignore +++ b/build/.gitignore @@ -8,3 +8,6 @@ /CPackConfig.cmake /CPackSourceConfig.cmake /install_manifest.txt +# windows build script +i2pd*.zip +build*.log diff --git a/build/build_mingw.cmd b/build/build_mingw.cmd new file mode 100644 index 00000000..022df45e --- /dev/null +++ b/build/build_mingw.cmd @@ -0,0 +1,62 @@ +@echo off +setlocal enableextensions enabledelayedexpansion +title Building i2pd + +REM Copyright (c) 2013-2017, The PurpleI2P Project +REM This file is part of Purple i2pd project and licensed under BSD3 +REM See full license text in LICENSE file at top of project tree + +REM To use that script, you must have installed in your MSYS installation theese packages: +REM Base: git make zip +REM x86_64: mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-gcc +REM i686: mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-gcc + +REM setting up variables for MSYS +REM Note: if you installed MSYS64 to different path, edit WD variable (only C:\msys64 needed to edit)! +set "WD=C:\msys64\usr\bin\" +set MSYS2_PATH_TYPE=inherit +set CHERE_INVOKING=enabled_from_arguments +set MSYSTEM=MSYS + +REM detecting number of processors and subtract 1. +set /a threads=%NUMBER_OF_PROCESSORS%-1 + +REM we must work in root of repo +cd .. + +echo Receiving latest commit and cleaning up... +"%WD%bash" -lc "git pull && make clean" > build/build_git.log 2>&1 +echo. + +REM set to variable current commit hash +FOR /F "usebackq" %%a IN (`%WD%bash -lc 'git describe --tags'`) DO ( + set tag=%%a +) + +REM starting building +set MSYSTEM=MINGW32 +set bitness=32 +call :BUILDING +echo. + +set MSYSTEM=MINGW64 +set bitness=64 +call :BUILDING +echo. + +echo Build complete... +pause +exit /b 0 + +:BUILDING +echo Building i2pd %tag% for win%bitness%: +echo Build AVX+AESNI... +"%WD%bash" -lc "make USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j%threads% && zip -9 build/i2pd_%tag%_win%bitness%_mingw_avx_aesni.zip i2pd.exe && make clean" > build/build_win%bitness%_avx_aesni.log 2>&1 +echo Build AVX... +"%WD%bash" -lc "make USE_UPNP=yes USE_AVX=1 -j%threads% && zip -9 build/i2pd_%tag%_win%bitness%_mingw_avx.zip i2pd.exe && make clean" > build/build_win%bitness%_avx.log 2>&1 +echo Build AESNI... +"%WD%bash" -lc "make USE_UPNP=yes USE_AESNI=1 -j%threads% && zip -9 build/i2pd_%tag%_win%bitness%_mingw_aesni.zip i2pd.exe && make clean" > build/build_win%bitness%_aesni.log 2>&1 +echo Build without extensions... +"%WD%bash" -lc "make USE_UPNP=yes -j%threads% && zip -9 build/i2pd_%tag%_win%bitness%_mingw.zip i2pd.exe && make clean" > build/build_win%bitness%.log 2>&1 + +:EOF \ No newline at end of file diff --git a/contrib/.gitignore b/contrib/.gitignore deleted file mode 100644 index d736e035..00000000 --- a/contrib/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -i2pd*.zip -build*.log \ No newline at end of file diff --git a/contrib/build_mingw.cmd b/contrib/build_mingw.cmd deleted file mode 100644 index b104d79c..00000000 --- a/contrib/build_mingw.cmd +++ /dev/null @@ -1,25 +0,0 @@ -@echo off -setlocal - -title Building i2pd - -set "WD=C:\msys64\usr\bin\" -set MSYS2_PATH_TYPE=inherit -set CHERE_INVOKING=enabled_from_arguments -set MSYSCON= - -echo Building i2pd for win32. Press Enter after the end of compilation... -set MSYSTEM=MINGW32 -set CONTITLE=MinGW x32 -start "%CONTITLE%" /WAIT "%WD%bash" --login build_mingw.sh -pause > nul - -echo Building i2pd for win64. Press Enter after the end of compilation... -set MSYSTEM=MINGW64 -set CONTITLE=MinGW x64 -start "%CONTITLE%" /WAIT "%WD%bash" --login build_mingw.sh -pause > nul - -echo Build complete... -pause -exit /b 0 \ No newline at end of file diff --git a/contrib/build_mingw.sh b/contrib/build_mingw.sh deleted file mode 100644 index ecc388c1..00000000 --- a/contrib/build_mingw.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/sh - -# Определяем архитектуру. -if [ $MSYSTEM == MINGW64 ]; then - export arch="win64" -elif [ $MSYSTEM == MINGW32 ]; then - export arch="win32" -else - echo "Не могу понять, какая у вас архитектура, используемая для сборки."; - echo "Вы точно запустили скрипт в оболочке MSYS2 MinGW [64/32]-bit ?"; - echo "Обычно её можно запустить выполнив c:\msys64\mingw64.exe или c:\msys64\mingw32.exe"; - exit 1; -fi; - -# Задаём переменной contrib текущий путь и переходим на уровень выше. -export contrib=$PWD -cd .. - -# Очистка от предыдущей сборки (на всякий случай =) ). -make clean >> /dev/null - -# Обновляем репозиторий, и получаем хеш последнего коммита. -echo "Получаем обновления из репозитория."; -git pull -if [ "$?" != 0 ]; then - echo "Не удалось обновить локальный репозиторий."; - echo "Вы точно запустили скрипт в папке репозитория?"; - exit 1; -fi; - -export commit=$(git rev-parse --verify HEAD | cut -c -7) -if [ -z commit ]; then - echo "Не удалось получить хеш последнего коммита."; - echo "Вы точно запустили скрипт в папке репозитория?"; - exit 1; -fi; - -# Получаем версию приложения -export version=$(grep -E "I2PD_VERSION_(MAJOR|MINOR|MICRO)\ " version.h | grep -oE '[^ ]+$' | tr '\n' '.'|head -c -1) - -# Получаем количество ядер, и уменьшаем количество потоков на 1 от количества ядер (если их больше чем 1). -if [ $NUMBER_OF_PROCESSORS -ge 2 ]; then - export threads=$(( $NUMBER_OF_PROCESSORS - 1 )) -else - export threads=$NUMBER_OF_PROCESSORS -fi; - -echo "Собираем i2pd ${version} (коммит ${commit}) для ${arch}."; - -# Собираем приложение с разными параметрами, и архивируем в zip архивы. -echo "Сборка AVX+AESNI"; -make USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j ${threads} > ${contrib}/build_${arch}_avx_aesni.log 2>&1 -if [ "$?" != 0 ]; then - echo "Сборка не удалась. Смотрите в build_avx_aesni.log"; - exit 1; -fi; -zip -9 ${contrib}/i2pd_${version}_${commit}_${arch}_mingw_avx_aesni.zip i2pd.exe >> /dev/null -make clean >> /dev/null - -echo "Сборка AVX"; -make USE_UPNP=yes USE_AVX=1 -j ${threads} > ${contrib}/build_${arch}_avx.log 2>&1 -if [ "$?" != 0 ]; then - echo "Сборка не удалась. Смотрите в build_avx.log."; - exit 1; -fi; -zip -9 ${contrib}/i2pd_${version}_${commit}_${arch}_mingw_avx.zip i2pd.exe >> /dev/null -make clean >> /dev/null - -echo "Сборка AESNI"; -make USE_UPNP=yes USE_AESNI=1 -j ${threads} > ${contrib}/build_${arch}_aesni.log 2>&1 -if [ "$?" != 0 ]; then - echo "Сборка не удалась. Смотрите в build_aesni.log"; - exit 1; -fi; -zip -9 ${contrib}/i2pd_${version}_${commit}_${arch}_mingw_aesni.zip i2pd.exe >> /dev/null -make clean >> /dev/null - -echo "Сборка без дополнительных инструкций"; -make USE_UPNP=yes -j ${threads} > ${contrib}/build_${arch}.log 2>&1 -if [ "$?" != 0 ]; then - echo "Сборка не удалась. Смотрите в build.log"; - exit 1; -fi; -zip -9 ${contrib}/i2pd_${version}_${commit}_${arch}_mingw.zip i2pd.exe >> /dev/null -make clean >> /dev/null - -echo "Сборка i2pd ${version} для ${arch} завершена."; -exit 0; diff --git a/tests/Makefile b/tests/Makefile index ef30c631..d1284602 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,7 +1,6 @@ CXXFLAGS += -Wall -Wextra -pedantic -O0 -g -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1 -TESTS = test-http-url test-http-req test-http-res test-http-url_decode \ - test-http-merge_chunked test-base-64 +TESTS = test-gost test-gost-sig test-base-64 all: $(TESTS) run @@ -11,6 +10,12 @@ test-http-%: ../HTTP.cpp test-http-%.cpp test-base-%: ../Base.cpp test-base-%.cpp $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ +test-gost: ../Gost.cpp ../I2PEndian.cpp test-gost.cpp + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto + +test-gost-sig: ../Gost.cpp ../I2PEndian.cpp ../Signature.cpp ../Crypto.cpp ../Log.cpp test-gost-sig.cpp + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system + run: $(TESTS) @for TEST in $(TESTS); do ./$$TEST ; done diff --git a/tests/test-gost-sig.cpp b/tests/test-gost-sig.cpp new file mode 100644 index 00000000..63f7b27e --- /dev/null +++ b/tests/test-gost-sig.cpp @@ -0,0 +1,35 @@ +#include +#include +#include + +#include "../Gost.h" +#include "../Signature.h" + +const uint8_t example2[72] = +{ + 0xfb,0xe2,0xe5,0xf0,0xee,0xe3,0xc8,0x20,0xfb,0xea,0xfa,0xeb,0xef,0x20,0xff,0xfb, + 0xf0,0xe1,0xe0,0xf0,0xf5,0x20,0xe0,0xed,0x20,0xe8,0xec,0xe0,0xeb,0xe5,0xf0,0xf2, + 0xf1,0x20,0xff,0xf0,0xee,0xec,0x20,0xf1,0x20,0xfa,0xf2,0xfe,0xe5,0xe2,0x20,0x2c, + 0xe8,0xf6,0xf3,0xed,0xe2,0x20,0xe8,0xe6,0xee,0xe1,0xe8,0xf0,0xf2,0xd1,0x20,0x2c, + 0xe8,0xf0,0xf2,0xe5,0xe2,0x20,0xe5,0xd1 +}; + + +int main () +{ + uint8_t priv[64], pub[128], signature[128]; + i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, priv, pub); + i2p::crypto::GOSTR3410_512_Signer signer (i2p::crypto::eGOSTR3410TC26A512, priv); + signer.Sign (example2, 72, signature); + i2p::crypto::GOSTR3410_512_Verifier verifier (i2p::crypto::eGOSTR3410TC26A512, pub); + assert (verifier.Verify (example2, 72, signature)); + + i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410CryptoProA, priv, pub); + i2p::crypto::GOSTR3410_256_Signer signer1 (i2p::crypto::eGOSTR3410CryptoProA, priv); + signer1.Sign (example2, 72, signature); + i2p::crypto::GOSTR3410_256_Verifier verifier1 (i2p::crypto::eGOSTR3410CryptoProA, pub); + assert (verifier1.Verify (example2, 72, signature)); +} + + + diff --git a/tests/test-gost.cpp b/tests/test-gost.cpp new file mode 100644 index 00000000..b0ab1d51 --- /dev/null +++ b/tests/test-gost.cpp @@ -0,0 +1,69 @@ +#include +#include +#include + +#include "../Gost.h" + +const uint8_t example1[63] = +{ + 0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37, + 0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31, + 0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35, + 0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30 +}; + +const uint8_t example2[72] = +{ + 0xfb,0xe2,0xe5,0xf0,0xee,0xe3,0xc8,0x20,0xfb,0xea,0xfa,0xeb,0xef,0x20,0xff,0xfb, + 0xf0,0xe1,0xe0,0xf0,0xf5,0x20,0xe0,0xed,0x20,0xe8,0xec,0xe0,0xeb,0xe5,0xf0,0xf2, + 0xf1,0x20,0xff,0xf0,0xee,0xec,0x20,0xf1,0x20,0xfa,0xf2,0xfe,0xe5,0xe2,0x20,0x2c, + 0xe8,0xf6,0xf3,0xed,0xe2,0x20,0xe8,0xe6,0xee,0xe1,0xe8,0xf0,0xf2,0xd1,0x20,0x2c, + 0xe8,0xf0,0xf2,0xe5,0xe2,0x20,0xe5,0xd1 +}; + +const uint8_t example1_hash_512[64] = +{ + 0x48,0x6f,0x64,0xc1,0x91,0x78,0x79,0x41,0x7f,0xef,0x08,0x2b,0x33,0x81,0xa4,0xe2, + 0x11,0xc3,0x24,0xf0,0x74,0x65,0x4c,0x38,0x82,0x3a,0x7b,0x76,0xf8,0x30,0xad,0x00, + 0xfa,0x1f,0xba,0xe4,0x2b,0x12,0x85,0xc0,0x35,0x2f,0x22,0x75,0x24,0xbc,0x9a,0xb1, + 0x62,0x54,0x28,0x8d,0xd6,0x86,0x3d,0xcc,0xd5,0xb9,0xf5,0x4a,0x1a,0xd0,0x54,0x1b +}; + +const uint8_t example1_hash_256[32] = +{ + 0x00,0x55,0x7b,0xe5,0xe5,0x84,0xfd,0x52,0xa4,0x49,0xb1,0x6b,0x02,0x51,0xd0,0x5d, + 0x27,0xf9,0x4a,0xb7,0x6c,0xba,0xa6,0xda,0x89,0x0b,0x59,0xd8,0xef,0x1e,0x15,0x9d +}; + +const uint8_t example2_hash_512[64] = +{ + 0x28,0xfb,0xc9,0xba,0xda,0x03,0x3b,0x14,0x60,0x64,0x2b,0xdc,0xdd,0xb9,0x0c,0x3f, + 0xb3,0xe5,0x6c,0x49,0x7c,0xcd,0x0f,0x62,0xb8,0xa2,0xad,0x49,0x35,0xe8,0x5f,0x03, + 0x76,0x13,0x96,0x6d,0xe4,0xee,0x00,0x53,0x1a,0xe6,0x0f,0x3b,0x5a,0x47,0xf8,0xda, + 0xe0,0x69,0x15,0xd5,0xf2,0xf1,0x94,0x99,0x6f,0xca,0xbf,0x26,0x22,0xe6,0x88,0x1e +}; + +const uint8_t example2_hash_256[32] = +{ + 0x50,0x8f,0x7e,0x55,0x3c,0x06,0x50,0x1d,0x74,0x9a,0x66,0xfc,0x28,0xc6,0xca,0xc0, + 0xb0,0x05,0x74,0x6d,0x97,0x53,0x7f,0xa8,0x5d,0x9e,0x40,0x90,0x4e,0xfe,0xd2,0x9d +}; + +int main () +{ + uint8_t digest[64]; + i2p::crypto::GOSTR3411_2012_512 (example1, 63, digest); + assert(memcmp (digest, example1_hash_512, 64) == 0); + + i2p::crypto::GOSTR3411_2012_256 (example1, 63, digest); + assert(memcmp (digest, example1_hash_256, 32) == 0); + + i2p::crypto::GOSTR3411_2012_512 (example2, 72, digest); + assert(memcmp (digest, example2_hash_512, 64) == 0); + + i2p::crypto::GOSTR3411_2012_256 (example2, 72, digest); + assert(memcmp (digest, example2_hash_256, 32) == 0); +} + + +