diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/channel.cpp | 73 | ||||
| -rw-r--r-- | src/channel.h | 29 | ||||
| -rw-r--r-- | src/network.cpp | 20 | ||||
| -rw-r--r-- | src/network.h | 2 | 
4 files changed, 58 insertions, 66 deletions
| diff --git a/src/channel.cpp b/src/channel.cpp index 787fb08..f5cfb9c 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -3,8 +3,6 @@  #include <algorithm>  #include <stdexcept> -#include <openssl/rand.h> -  using std::remove_const;  using std::runtime_error; @@ -70,54 +68,26 @@ ChannelAcceptData ChannelAcceptData::load(const Ref & ref)  	};  } -Stored<Channel> ChannelAcceptData::channel() const +unique_ptr<Channel> ChannelAcceptData::channel() const  { -	const auto & st = request.ref().storage(); -  	if (auto secret = SecretKexKey::load(key)) -		return st.store(Channel( +		return make_unique<Channel>(  			request->data->peers, -			secret->dh(*request->data->key) -		)); +			secret->dh(*request->data->key), +			false +		);  	if (auto secret = SecretKexKey::load(request->data->key)) -		return st.store(Channel( +		return make_unique<Channel>(  			request->data->peers, -			secret->dh(*key) -		)); +			secret->dh(*key), +			true +		);  	throw runtime_error("failed to load secret DH key");  } -Ref Channel::store(const Storage & st) const -{ -	vector<Record::Item> items; - -	for (const auto & p : peers) -		items.emplace_back("peer", p); -	items.emplace_back("enc", "aes-128-gcm"); -	items.emplace_back("key", key); - -	return st.storeObject(Record(std::move(items))); -} - -Channel Channel::load(const Ref & ref) -{ -	if (auto rec = ref->asRecord()) { -		remove_const<decltype(peers)>::type peers; -		for (const auto & i : rec->items("peer")) -			if (auto p = i.as<Signed<IdentityData>>()) -				peers.push_back(*p); - -		if (rec->item("enc").asText() == "aes-128-gcm") -			if (auto key = rec->item("key").asBinary()) -				return Channel(peers, std::move(*key)); -	} - -	return Channel({}, {}); -} -  Stored<ChannelRequest> Channel::generateRequest(const Storage & st,  		const Identity & self, const Identity & peer)  { @@ -165,20 +135,23 @@ optional<Stored<ChannelAccept>> Channel::acceptRequest(const Identity & self,  	}));  } -vector<uint8_t> Channel::encrypt(const vector<uint8_t> & plain) const +vector<uint8_t> Channel::encrypt(const vector<uint8_t> & plain)  { -	vector<uint8_t> res(plain.size() + 12 + 16 + 16); +	vector<uint8_t> res(plain.size() + 8 + 16 + 16); +	array<uint8_t, 12> iv; -	if (RAND_bytes(res.data(), 12) != 1) -		throw runtime_error("failed to generate random IV"); +	uint64_t beCount = htobe64(nonceCounter++); +	std::copy_n(&beCount, 6, res.begin()); +	std::copy_n(nonceFixedOur.begin(), 6, iv.begin()); +	std::copy_n(res.begin() + 2, 6, iv.begin() + 6);  	const unique_ptr<EVP_CIPHER_CTX, void(*)(EVP_CIPHER_CTX*)>  		ctx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);  	EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_gcm(), -			nullptr, key.data(), res.data()); +			nullptr, key.data(), iv.data());  	int outl = 0; -	uint8_t * cur = res.data() + 12; +	uint8_t * cur = res.data() + 8;  	if (EVP_EncryptUpdate(ctx.get(), cur, &outl, plain.data(), plain.size()) != 1)  		throw runtime_error("failed to encrypt data"); @@ -195,20 +168,24 @@ vector<uint8_t> Channel::encrypt(const vector<uint8_t> & plain) const  	return res;  } -optional<vector<uint8_t>> Channel::decrypt(const vector<uint8_t> & ctext) const +optional<vector<uint8_t>> Channel::decrypt(const vector<uint8_t> & ctext)  {  	vector<uint8_t> res(ctext.size()); +	array<uint8_t, 12> iv; + +	std::copy_n(nonceFixedPeer.begin(), 6, iv.begin()); +	std::copy_n(ctext.begin() + 2, 6, iv.begin() + 6);  	const unique_ptr<EVP_CIPHER_CTX, void(*)(EVP_CIPHER_CTX*)>  		ctx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);  	EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_gcm(), -			nullptr, key.data(), ctext.data()); +			nullptr, key.data(), iv.data());  	int outl = 0;  	uint8_t * cur = res.data();  	if (EVP_DecryptUpdate(ctx.get(), cur, &outl, -				ctext.data() + 12, ctext.size() - 12 - 16) != 1) +				ctext.data() + 8, ctext.size() - 8 - 16) != 1)  		return nullopt;  	cur += outl; diff --git a/src/channel.h b/src/channel.h index 1c7df30..5f1786e 100644 --- a/src/channel.h +++ b/src/channel.h @@ -4,8 +4,15 @@  #include "identity.h" +#include <atomic> +#include <memory> +  namespace erebos { +using std::array; +using std::atomic; +using std::unique_ptr; +  struct ChannelRequestData  {  	Ref store(const Storage & st) const; @@ -22,7 +29,7 @@ struct ChannelAcceptData  	Ref store(const Storage & st) const;  	static ChannelAcceptData load(const Ref &); -	Stored<class Channel> channel() const; +	unique_ptr<class Channel> channel() const;  	const Stored<ChannelRequest> request;  	const Stored<PublicKexKey> key; @@ -34,25 +41,33 @@ class Channel  {  public:  	Channel(const vector<Stored<Signed<IdentityData>>> & peers, -			vector<uint8_t> && key): +			vector<uint8_t> && key, bool ourRequest):  		peers(peers), -		key(std::move(key)) +		key(std::move(key)), +		nonceFixedOur({ uint8_t(ourRequest ? 1 : 2), 0, 0, 0, 0, 0 }), +		nonceFixedPeer({ uint8_t(ourRequest ? 2 : 1), 0, 0, 0, 0, 0 })  	{} -	Ref store(const Storage & st) const; -	static Channel load(const Ref &); +	Channel(const Channel &) = delete; +	Channel(Channel &&) = delete; +	Channel & operator=(const Channel &) = delete; +	Channel & operator=(Channel &&) = delete;  	static Stored<ChannelRequest> generateRequest(const Storage &,  			const Identity & self, const Identity & peer);  	static optional<Stored<ChannelAccept>> acceptRequest(const Identity & self,  			const Identity & peer, const Stored<ChannelRequest> & request); -	vector<uint8_t> encrypt(const vector<uint8_t> &) const; -	optional<vector<uint8_t>> decrypt(const vector<uint8_t> &) const; +	vector<uint8_t> encrypt(const vector<uint8_t> &); +	optional<vector<uint8_t>> decrypt(const vector<uint8_t> &);  private:  	const vector<Stored<Signed<IdentityData>>> peers;  	const vector<uint8_t> key; + +	const array<uint8_t, 6> nonceFixedOur; +	const array<uint8_t, 6> nonceFixedPeer; +	atomic<uint64_t> nonceCounter = 0;  };  } diff --git a/src/network.cpp b/src/network.cpp index b735262..84c3083 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -135,7 +135,7 @@ void Peer::Priv::notifyWatchers()  bool Peer::hasChannel() const  {  	if (auto speer = p->speer.lock()) -		return holds_alternative<Stored<Channel>>(speer->channel); +		return holds_alternative<unique_ptr<Channel>>(speer->channel);  	return false;  } @@ -306,8 +306,8 @@ void Server::Priv::doListen()  		auto & peer = getPeer(paddr);  		current = &buf; -		if (holds_alternative<Stored<Channel>>(peer.channel)) { -			if (auto dec = std::get<Stored<Channel>>(peer.channel)->decrypt(buf)) { +		if (holds_alternative<unique_ptr<Channel>>(peer.channel)) { +			if (auto dec = std::get<unique_ptr<Channel>>(peer.channel)->decrypt(buf)) {  				decrypted = std::move(*dec);  				current = &decrypted;  			} @@ -421,14 +421,14 @@ void Server::Priv::handlePacket(Server::Peer & peer, const TransportHeader & hea  			if (auto pref = std::get<PartialRef>(item.value)) {  				if (holds_alternative<Stored<ChannelAccept>>(peer.channel) &&  						std::get<Stored<ChannelAccept>>(peer.channel).ref().digest() == pref.digest()) -					peer.channel.emplace<Stored<Channel>> +					peer.channel.emplace<unique_ptr<Channel>>  						(std::get<Stored<ChannelAccept>>(peer.channel)->data->channel());  			}  			break;  		case TransportHeader::Type::DataRequest: {  			auto pref = std::get<PartialRef>(item.value); -			if (holds_alternative<Stored<Channel>>(peer.channel) || +			if (holds_alternative<unique_ptr<Channel>>(peer.channel) ||  					plaintextRefs.find(pref.digest()) != plaintextRefs.end()) {  				if (auto ref = peer.tempStorage.ref(pref.digest())) {  					TransportHeader::Item hitem { TransportHeader::Type::DataResponse, *ref }; @@ -514,7 +514,7 @@ void Server::Priv::handlePacket(Server::Peer & peer, const TransportHeader & hea  					if (holds_alternative<Identity>(peer.identity) &&  							acc.isSignedBy(std::get<Identity>(peer.identity).keyMessage())) {  						reply.header({ TransportHeader::Type::Acknowledged, pref }); -						peer.channel.emplace<Stored<Channel>>(acc.data->channel()); +						peer.channel.emplace<unique_ptr<Channel>>(acc.data->channel());  					}  				}  			} @@ -578,8 +578,8 @@ void Server::Peer::send(const TransportHeader & header, const vector<Object> & o  		data.insert(data.end(), part.begin(), part.end());  	} -	if (holds_alternative<Stored<Channel>>(channel)) -		out = std::get<Stored<Channel>>(channel)->encrypt(data); +	if (holds_alternative<unique_ptr<Channel>>(channel)) +		out = std::get<unique_ptr<Channel>>(channel)->encrypt(data);  	else if (secure)  		secureOutQueue.emplace_back(move(data));  	else @@ -676,11 +676,11 @@ void Server::Peer::trySendOutQueue()  	if (secureOutQueue.empty())  		return; -	if (!holds_alternative<Stored<Channel>>(channel)) +	if (!holds_alternative<unique_ptr<Channel>>(channel))  		return;  	for (const auto & data : secureOutQueue) { -		auto out = std::get<Stored<Channel>>(channel)->encrypt(data); +		auto out = std::get<unique_ptr<Channel>>(channel)->encrypt(data);  		sendto(server.sock, out.data(), out.size(), 0,  				(sockaddr *) &addr, sizeof(addr)); diff --git a/src/network.h b/src/network.h index a59a1bc..40c06bf 100644 --- a/src/network.h +++ b/src/network.h @@ -50,7 +50,7 @@ struct Server::Peer  		Stored<ChannelRequest>,  		shared_ptr<struct WaitingRef>,  		Stored<ChannelAccept>, -		Stored<Channel>> channel; +		unique_ptr<Channel>> channel;  	Storage tempStorage;  	PartialStorage partStorage; |