diff --git a/include/llarp/encrypted_frame.hpp b/include/llarp/encrypted_frame.hpp index 8bc97be5b..1655ea03c 100644 --- a/include/llarp/encrypted_frame.hpp +++ b/include/llarp/encrypted_frame.hpp @@ -25,7 +25,7 @@ namespace llarp DecryptInPlace(byte_t* seckey, llarp_crypto* crypto); bool - EncryptInPlace(byte_t* seckey, llarp_crypto* crypto); + EncryptInPlace(byte_t* seckey, byte_t* other, llarp_crypto* crypto); }; /// TOOD: can only handle 1 frame at a time @@ -40,7 +40,7 @@ namespace llarp AsyncFrameEncrypter< User >* ctx = static_cast< AsyncFrameEncrypter< User >* >(user); - if(ctx->frame->EncryptInPlace(ctx->seckey, ctx->crypto)) + if(ctx->frame->EncryptInPlace(ctx->seckey, ctx->otherKey, ctx->crypto)) ctx->handler(ctx->frame, ctx->user); else { @@ -54,6 +54,7 @@ namespace llarp EncryptHandler handler; EncryptedFrame* frame; User* user; + byte_t* otherKey; AsyncFrameEncrypter(llarp_crypto* c, byte_t* seckey, EncryptHandler h) : crypto(c), secretkey(seckey), handler(h) @@ -61,9 +62,12 @@ namespace llarp } void - AsyncEncrypt(llarp_threadpool* worker, llarp_buffer_t buf, User* u) + AsyncEncrypt(llarp_threadpool* worker, llarp_buffer_t buf, byte_t* other, + User* u) { - frame = new EncryptedFrame(buf.sz); + // TODO: should we own otherKey? + otherKey = other; + frame = new EncryptedFrame(buf.sz); memcpy(frame->data + EncryptedFrame::OverheadSize, buf.base, buf.sz); user = u; llarp_threadpool_queue_job(worker, {this, &Encrypt}); diff --git a/llarp/encrypted_frame.cpp b/llarp/encrypted_frame.cpp index 457c2d903..29e19ae43 100644 --- a/llarp/encrypted_frame.cpp +++ b/llarp/encrypted_frame.cpp @@ -1,3 +1,4 @@ +#include #include #include "logger.hpp" @@ -24,6 +25,64 @@ namespace llarp delete[] data; } + bool + EncryptedFrame::EncryptInPlace(byte_t* ourSecretKey, byte_t* otherPubkey, + llarp_crypto* crypto) + { + // format of frame is + // <32 bytes keyed hash of following data> + // <32 bytes nonce> + // <32 bytes pubkey> + // + // + byte_t* hash = data; + byte_t* nonce = hash + sizeof(llarp_shorthash_t); + byte_t* pubkey = nonce + sizeof(llarp_tunnel_nonce_t); + byte_t* body = pubkey + sizeof(llarp_pubkey_t); + + llarp_sharedkey_t shared; + + auto DH = crypto->dh_client; + auto Encrypt = crypto->xchacha20; + auto MDS = crypto->hmac; + + llarp_buffer_t buf; + buf.base = body; + buf.cur = buf.base; + buf.sz = size - OverheadSize; + + // set our pubkey + memcpy(pubkey, llarp::seckey_topublic(ourSecretKey), + sizeof(llarp_pubkey_t)); + // randomize nonce + crypto->randbytes(nonce, sizeof(llarp_tunnel_nonce_t)); + + // derive shared key + if(!DH(shared, otherPubkey, nonce, ourSecretKey)) + { + llarp::Error("DH failed"); + return false; + } + // encrypt body + if(!Encrypt(buf, shared, nonce)) + { + llarp::Error("encrypt failed"); + return false; + } + + // generate message auth + buf.base = nonce; + buf.cur = buf.base; + buf.sz = size - sizeof(llarp_shorthash_t); + + if(!MDS(hash, buf, shared)) + { + llarp::Error("Failed to generate messgae auth"); + return false; + } + return true; + } + bool EncryptedFrame::DecryptInPlace(byte_t* ourSecretKey, llarp_crypto* crypto) { @@ -39,19 +98,19 @@ namespace llarp // // byte_t* hash = data; - byte_t* nonce = hash + sizeof(llarp_pubkey_t); + byte_t* nonce = hash + sizeof(llarp_shorthash_t); byte_t* otherPubkey = nonce + sizeof(llarp_tunnel_nonce_t); - byte_t* body = otherPubkey + sizeof(llarp_shorthash_t); + byte_t* body = otherPubkey + sizeof(llarp_pubkey_t); // use dh_server becuase we are not the creator of this message auto DH = crypto->dh_server; auto Decrypt = crypto->xchacha20; - auto Digest = crypto->hmac; + auto MDS = crypto->hmac; llarp_buffer_t buf; - buf.base = body; + buf.base = nonce; buf.cur = buf.base; - buf.sz = size - OverheadSize; + buf.sz = size - sizeof(llarp_shorthash_t); llarp_sharedkey_t shared; llarp_shorthash_t digest; @@ -62,7 +121,7 @@ namespace llarp return false; } - if(!Digest(digest, buf, shared)) + if(!MDS(digest, buf, shared)) { llarp::Error("Digest failed"); return false; @@ -74,6 +133,10 @@ namespace llarp return false; } + buf.base = body; + buf.cur = body; + buf.sz = size - OverheadSize; + if(!Decrypt(buf, shared, nonce)) { llarp::Error("decrypt failed");