Skip to content

Commit

Permalink
Merge pull request PurpleI2P#842 from PurpleI2P/openssl
Browse files Browse the repository at this point in the history
2.13.0
  • Loading branch information
orignal authored Apr 6, 2017
2 parents b2d2c56 + 4e1fcbb commit 46cb95f
Show file tree
Hide file tree
Showing 15 changed files with 190 additions and 46 deletions.
14 changes: 14 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog

## [2.13.0] - 2017-04-06
### Added
- Persist local destination's tags
- GOST signature types 9 and 10
- Exploratory tunnels configuration
### Changed
- Reseed servers list
- Inactive NTCP sockets get closed faster
- Some EdDSA speed up
### Fixed
- Multiple acceptors for SAM
- Follow on data after STREAM CREATE for SAM
- Memory leaks

## [2.12.0] - 2017-02-14
### Added
- Additional HTTP and SOCKS proxy tunnels
Expand Down
33 changes: 28 additions & 5 deletions Crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,13 +289,26 @@ namespace crypto
#if (OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER) // 1.1.0 or LibreSSL
// define getters and setters introduced in 1.1.0
inline int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
{ d->p = p; d->q = q; d->g = g; return 1; }
{
if (d->p) BN_free (d->p);
if (d->q) BN_free (d->q);
if (d->g) BN_free (d->g);
d->p = p; d->q = q; d->g = g; return 1;
}
inline int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
{ d->pub_key = pub_key; d->priv_key = priv_key; return 1; }
{
if (d->pub_key) BN_free (d->pub_key);
if (d->priv_key) BN_free (d->priv_key);
d->pub_key = pub_key; d->priv_key = priv_key; return 1;
}
inline void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key)
{ *pub_key = d->pub_key; *priv_key = d->priv_key; }
inline int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
{ sig->r = r; sig->s = s; return 1; }
{
if (sig->r) BN_free (sig->r);
if (sig->s) BN_free (sig->s);
sig->r = r; sig->s = s; return 1;
}
inline void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{ *pr = sig->r; *ps = sig->s; }

Expand All @@ -309,12 +322,22 @@ inline void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM
{ *pr = sig->r; *ps = sig->s; }

inline int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
{ r->n = n; r->e = e; r->d = d; return 1; }
{
if (r->n) BN_free (r->n);
if (r->e) BN_free (r->e);
if (r->d) BN_free (r->d);
r->n = n; r->e = e; r->d = d; return 1;
}
inline void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
{ *n = r->n; *e = r->e; *d = r->d; }

inline int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
{ dh->p = p; dh->q = q; dh->g = g; return 1; }
{
if (dh->p) BN_free (dh->p);
if (dh->q) BN_free (dh->q);
if (dh->g) BN_free (dh->g);
dh->p = p; dh->q = q; dh->g = g; return 1;
}
inline int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
{
if (dh->pub_key) BN_free (dh->pub_key);
Expand Down
2 changes: 2 additions & 0 deletions Destination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ namespace client
{
if (!m_IsRunning)
{
LoadTags ();
m_IsRunning = true;
m_Pool->SetLocalDestination (shared_from_this ());
m_Pool->SetActive (true);
Expand Down Expand Up @@ -145,6 +146,7 @@ namespace client
delete m_Thread;
m_Thread = 0;
}
SaveTags ();
CleanUp (); // GarlicDestination
return true;
}
Expand Down
14 changes: 14 additions & 0 deletions FS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "Base.h"
#include "FS.h"
#include "Log.h"
#include "Garlic.h"

namespace i2p {
namespace fs {
Expand Down Expand Up @@ -93,6 +94,11 @@ namespace fs {
std::string destinations = DataDirPath("destinations");
if (!boost::filesystem::exists(destinations))
boost::filesystem::create_directory(destinations);
std::string tags = DataDirPath("tags");
if (!boost::filesystem::exists(tags))
boost::filesystem::create_directory(tags);
else
i2p::garlic::CleanUpTagsFiles ();

return true;
}
Expand All @@ -116,6 +122,14 @@ namespace fs {
return boost::filesystem::exists(path);
}

uint32_t GetLastUpdateTime (const std::string & path)
{
if (!boost::filesystem::exists(path)) return 0;
boost::system::error_code ec;
auto t = boost::filesystem::last_write_time (path, ec);
return ec ? 0 : t;
}

bool Remove(const std::string & path) {
if (!boost::filesystem::exists(path))
return false;
Expand Down
4 changes: 3 additions & 1 deletion FS.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ namespace fs {
* @param files Vector to store found files
* @return true on success and false if directory not exists
*/
bool ReadDir(const std::string & path, std::vector<std::string> & files);
bool ReadDir(const std::string & path, std::vector<std::string> & files);

/**
* @brief Remove file with given path
Expand All @@ -112,6 +112,8 @@ namespace fs {
* @return true if file exists, false otherwise
*/
bool Exists(const std::string & path);

uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch

bool CreateDirectory (const std::string& path);

Expand Down
80 changes: 74 additions & 6 deletions Garlic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "Transports.h"
#include "Timestamp.h"
#include "Log.h"
#include "FS.h"
#include "Garlic.h"

namespace i2p
Expand Down Expand Up @@ -412,9 +413,7 @@ namespace garlic
if (key)
{
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
auto decryption = std::make_shared<i2p::crypto::CBCDecryption>();
decryption->SetKey (key);
m_Tags[SessionTag(tag, ts)] = decryption;
m_Tags[SessionTag(tag, ts)] = std::make_shared<AESDecryption>(key);
}
}

Expand Down Expand Up @@ -456,8 +455,7 @@ namespace garlic
ElGamalBlock elGamal;
if (length >= 514 && i2p::crypto::ElGamalDecrypt (GetEncryptionPrivateKey (), buf, (uint8_t *)&elGamal, m_Ctx, true))
{
auto decryption = std::make_shared<i2p::crypto::CBCDecryption>();
decryption->SetKey (elGamal.sessionKey);
auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
uint8_t iv[32]; // IV is first 16 bytes
SHA256(elGamal.preIV, 32, iv);
decryption->SetIV (iv);
Expand All @@ -469,7 +467,7 @@ namespace garlic
}
}

void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<i2p::crypto::CBCDecryption> decryption,
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
std::shared_ptr<i2p::tunnel::InboundTunnel> from)
{
uint16_t tagCount = bufbe16toh (buf);
Expand Down Expand Up @@ -714,5 +712,75 @@ namespace garlic
HandleDeliveryStatusMessage (msg);
}

void GarlicDestination::SaveTags ()
{
if (m_Tags.empty ()) return;
std::string ident = GetIdentHash().ToBase32();
std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags"));
std::ofstream f (path, std::ofstream::binary | std::ofstream::out | std::ofstream::trunc);
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
// 4 bytes timestamp, 32 bytes tag, 32 bytes key
for (auto it: m_Tags)
{
if (ts < it.first.creationTime + INCOMING_TAGS_EXPIRATION_TIMEOUT)
{
f.write ((char *)&it.first.creationTime, 4);
f.write ((char *)it.first.data (), 32);
f.write ((char *)it.second->GetKey ().data (), 32);
}
}
}

void GarlicDestination::LoadTags ()
{
std::string ident = GetIdentHash().ToBase32();
std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags"));
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
if (ts < i2p::fs::GetLastUpdateTime (path) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
{
// might contain non-expired tags
std::ifstream f (path, std::ifstream::binary);
if (f)
{
std::map<i2p::crypto::AESKey, std::shared_ptr<AESDecryption> > keys;
// 4 bytes timestamp, 32 bytes tag, 32 bytes key
while (!f.eof ())
{
uint32_t t;
uint8_t tag[32], key[32];
f.read ((char *)&t, 4); if (f.eof ()) break;
if (ts < t + INCOMING_TAGS_EXPIRATION_TIMEOUT)
{
f.read ((char *)tag, 32);
f.read ((char *)key, 32);
}
else
f.seekg (64, std::ios::cur); // skip
if (f.eof ()) break;

std::shared_ptr<AESDecryption> decryption;
auto it = keys.find (key);
if (it != keys.end ())
decryption = it->second;
else
decryption = std::make_shared<AESDecryption>(key);
m_Tags.insert (std::make_pair (SessionTag (tag, ts), decryption));
}
if (!m_Tags.empty ())
LogPrint (eLogInfo, m_Tags.size (), " loaded for ", ident);
}
}
i2p::fs::Remove (path);
}

void CleanUpTagsFiles ()
{
std::vector<std::string> files;
i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files);
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it: files)
if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
i2p::fs::Remove (it);
}
}
}
32 changes: 27 additions & 5 deletions Garlic.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ namespace garlic
uint32_t creationTime; // seconds since epoch
};

// AESDecryption is associated with session tags and store key
class AESDecryption: public i2p::crypto::CBCDecryption
{
public:

AESDecryption (const uint8_t * key): m_Key (key)
{
SetKey (key);
}
const i2p::crypto::AESKey& GetKey () const { return m_Key; };

private:

i2p::crypto::AESKey m_Key;
};

struct GarlicRoutingPath
{
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel;
Expand All @@ -67,7 +83,7 @@ namespace garlic
uint32_t updateTime; // seconds since epoch
int numTimesUsed;
};

class GarlicDestination;
class GarlicRoutingSession: public std::enable_shared_from_this<GarlicRoutingSession>
{
Expand Down Expand Up @@ -180,10 +196,13 @@ namespace garlic

void HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg);
void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);


void SaveTags ();
void LoadTags ();

private:

void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<i2p::crypto::CBCDecryption> decryption,
void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
std::shared_ptr<i2p::tunnel::InboundTunnel> from);
void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);

Expand All @@ -195,7 +214,7 @@ namespace garlic
std::mutex m_SessionsMutex;
std::map<i2p::data::IdentHash, GarlicRoutingSessionPtr> m_Sessions;
// incoming
std::map<SessionTag, std::shared_ptr<i2p::crypto::CBCDecryption>> m_Tags;
std::map<SessionTag, std::shared_ptr<AESDecryption> > m_Tags;
// DeliveryStatus
std::mutex m_DeliveryStatusSessionsMutex;
std::map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
Expand All @@ -205,7 +224,10 @@ namespace garlic
// for HTTP only
size_t GetNumIncomingTags () const { return m_Tags.size (); }
const decltype(m_Sessions)& GetSessions () const { return m_Sessions; };
};
};

void CleanUpTagsFiles ();

}
}

Expand Down
2 changes: 1 addition & 1 deletion Win32/installer.iss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#define I2Pd_AppName "i2pd"
#define I2Pd_ver "2.12.0"
#define I2Pd_ver "2.13.0"
#define I2Pd_Publisher "PurpleI2P"

[Setup]
Expand Down
2 changes: 1 addition & 1 deletion android/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.purplei2p.i2pd"
android:versionCode="1"
android:versionName="2.12.0">
android:versionName="2.13.0">
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="24"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: 2.12.{build}
version: 2.13.{build}
pull_requests:
do_not_increment_build_number: true
branches:
Expand Down
9 changes: 9 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
i2pd (2.13.0-1) unstable; urgency=low

* updated to version 2.13.0/0.9.29
* updated debian/control
* renamed logrotate to i2pd.logrotate
* fixed init.d script

-- orignal <orignal@i2pmail.org> Tue, 6 Apr 2017 14:00:00 +0000

i2pd (2.12.0-1) unstable; urgency=low

* updated to version 2.12.0/0.9.28
Expand Down
Loading

0 comments on commit 46cb95f

Please sign in to comment.