diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index 7e3c403cd..e826d6157 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -82,6 +82,22 @@ bool dev::decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext) return true; } +void dev::encryptECIES(Public const& _k, bytesConstRef _plain, bytes& o_cipher) +{ + bytes io = _plain.toBytes(); + s_secp256k1.encryptECIES(_k, io); + o_cipher = std::move(io); +} + +bool dev::decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext) +{ + bytes io = _cipher.toBytes(); + if (!s_secp256k1.decryptECIES(_k, io)) + return false; + o_plaintext = std::move(io); + return true; +} + void dev::encryptSym(Secret const& _k, bytesConstRef _plain, bytes& o_cipher) { // TOOD: @alex @subtly do this properly. diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index 92a13f9a5..2a5658991 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -96,6 +96,8 @@ void encryptSym(Secret const& _k, bytesConstRef _plain, bytes& o_cipher); /// Symmetric decryption. bool decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext); +void encryptECIES(Public const& _k, bytesConstRef _plain, bytes& o_cipher); +bool decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext); h128 encryptSymNoAuth(Secret const& _k, bytesConstRef _plain, bytes& o_cipher); h128 encryptSymNoAuth(Secret const& _k, bytesConstRef _plain, bytes& o_cipher, h128 const& _iv); bool decryptSymNoAuth(Secret const& _k, h128 const& _iv, bytesConstRef _cipher, bytes& o_plaintext); diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index e3c811a14..ba53cb7a7 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -90,16 +90,17 @@ void Secp256k1::encryptECIES(Public const& _k, bytes& io_cipher) if (!cipherText.size()) return; - bytes msg(1 + Public::size + cipherText.size() + 32); + bytes msg(1 + Public::size + h128::size + cipherText.size() + 32); msg[0] = 0x04; r.pub().ref().copyTo(bytesRef(&msg).cropped(1, Public::size)); - bytesRef msgCipherRef = bytesRef(&msg).cropped(1 + Public::size, cipherText.size()); + bytesRef msgCipherRef = bytesRef(&msg).cropped(1 + Public::size + h128::size, cipherText.size()); bytesConstRef(&cipherText).copyTo(msgCipherRef); // tag message CryptoPP::HMAC ctx(mKey.data(), mKey.size()); - ctx.Update(cipherText.data(), cipherText.size()); - ctx.Final(msg.data() + 1 + Public::size + cipherText.size()); + bytesConstRef cipherWithIV = bytesRef(&msg).cropped(1 + Public::size, h128::size + cipherText.size()); + ctx.Update(cipherWithIV.data(), cipherWithIV.size()); + ctx.Final(msg.data() + 1 + Public::size + cipherWithIV.size()); io_cipher.resize(msg.size()); io_cipher.swap(msg); @@ -114,7 +115,7 @@ bool Secp256k1::decryptECIES(Secret const& _k, bytes& io_text) // invalid message: publickey return false; - if (io_text.size() < (1 + Public::size + h256::size + 1)) + if (io_text.size() < (1 + Public::size + h128::size + 1 + h256::size)) // invalid message: length return false; @@ -126,13 +127,14 @@ bool Secp256k1::decryptECIES(Secret const& _k, bytes& io_text) sha3(mKey, mKey); bytes plain; - size_t cipherLen = io_text.size() - 1 - Public::size - h256::size; - bytesConstRef cipher(io_text.data() + 1 + Public::size, cipherLen); + size_t cipherLen = io_text.size() - 1 - Public::size - h128::size - h256::size; + bytesConstRef cipherWithIV(io_text.data() + 1 + Public::size, h128::size + cipherLen); + bytesConstRef cipher = cipherWithIV.cropped(h128::size, cipherLen); bytesConstRef msgMac(cipher.data() + cipher.size(), h256::size); // verify tag CryptoPP::HMAC ctx(mKey.data(), mKey.size()); - ctx.Update(cipher.data(), cipher.size()); + ctx.Update(cipherWithIV.data(), cipherWithIV.size()); h256 mac; ctx.Final(mac.data()); for (unsigned i = 0; i < h256::size; i++) diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 8d9994003..67a701eb3 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -408,7 +408,7 @@ void PeerHandshake::transition(boost::system::error_code _ech) host->m_alias.pub().ref().copyTo(pubk); this->nonce.ref().copyTo(nonce); auth[auth.size() - 1] = 0x0; - encrypt(remote, &auth, authCipher); + encryptECIES(remote, &auth, authCipher); ba::async_write(*socket, ba::buffer(authCipher), [this, self](boost::system::error_code ec, std::size_t) { @@ -419,14 +419,21 @@ void PeerHandshake::transition(boost::system::error_code _ech) { clog(NetConnect) << "devp2p.connect.ingress recving auth"; // ingress: rx auth - authCipher.resize(279); - ba::async_read(*socket, ba::buffer(authCipher, 279), [this, self](boost::system::error_code ec, std::size_t) + authCipher.resize(321); + ba::async_read(*socket, ba::buffer(authCipher, 321), [this, self](boost::system::error_code ec, std::size_t) { if (ec) transition(ec); else { - decrypt(host->m_alias.sec(), bytesConstRef(&authCipher), auth); + if (!decryptECIES(host->m_alias.sec(), bytesConstRef(&authCipher), auth)) + { + clog(NetWarn) << "devp2p.connect.egress recving auth decrypt failed"; + nextState = Error; + transition(); + return; + } + bytesConstRef sig(&auth[0], Signature::size); bytesConstRef hepubk(&auth[Signature::size], h256::size); bytesConstRef pubk(&auth[Signature::size + h256::size], Public::size); @@ -450,14 +457,21 @@ void PeerHandshake::transition(boost::system::error_code _ech) { clog(NetConnect) << "devp2p.connect.egress recving ack"; // egress: rx ack - ackCipher.resize(182); - ba::async_read(*socket, ba::buffer(ackCipher, 182), [this, self](boost::system::error_code ec, std::size_t) + ackCipher.resize(225); + ba::async_read(*socket, ba::buffer(ackCipher, 225), [this, self](boost::system::error_code ec, std::size_t) { if (ec) transition(ec); else { - decrypt(host->m_alias.sec(), bytesConstRef(&ackCipher), ack); + if (!decryptECIES(host->m_alias.sec(), bytesConstRef(&ackCipher), ack)) + { + clog(NetWarn) << "devp2p.connect.egress recving ack decrypt failed"; + nextState = Error; + transition(); + return; + } + bytesConstRef(&ack).cropped(0, Public::size).copyTo(remoteEphemeral.ref()); bytesConstRef(&ack).cropped(Public::size, h256::size).copyTo(remoteNonce.ref()); transition(); @@ -474,7 +488,7 @@ void PeerHandshake::transition(boost::system::error_code _ech) ecdhe.pubkey().ref().copyTo(epubk); this->nonce.ref().copyTo(nonce); ack[ack.size() - 1] = 0x0; - encrypt(remote, &ack, ackCipher); + encryptECIES(remote, &ack, ackCipher); ba::async_write(*socket, ba::buffer(ackCipher), [this, self](boost::system::error_code ec, std::size_t) { transition(ec); diff --git a/libp2p/Host.h b/libp2p/Host.h index 81016333a..86f682a1a 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -252,6 +252,7 @@ struct PeerHandshake: public std::enable_shared_from_this friend class Host; enum State { + Error = -1, New, // New->AckAuth [egress: tx auth, ingress: rx auth] AckAuth, // AckAuth->Authenticating [egress: rx ack, ingress: tx ack] Authenticating, // Authenticating [tx caps, rx caps, authenticate]