Browse Source

Got the new cryptoauth working with message-passthrough model

Caleb James DeLisle 3 years ago
parent
commit
7272cbdfc9

+ 1 - 1
crypto/test/CryptoAuthFuzz_oldnew_fuzz_test.c

@@ -22,5 +22,5 @@ void* CJDNS_FUZZ_INIT(struct Allocator* alloc, struct Random* rand)
 }
 void CJDNS_FUZZ_MAIN(void* vctx, struct Message* fuzz)
 {
-    //CryptoAuthFuzz_main(vctx, fuzz); TODO DISABLED TEST
+    CryptoAuthFuzz_main(vctx, fuzz);
 }

+ 2 - 2
crypto/test/CryptoAuth_test.c

@@ -159,7 +159,7 @@ static struct Message* encryptMsg(struct Context* ctx,
 {
     struct Allocator* alloc = Allocator_child(ctx->alloc);
     int len = (((CString_strlen(x)+1) / 8) + 1) * 8;
-    struct Message* msg = Message_new(len, CryptoHeader_SIZE, alloc);
+    struct Message* msg = Message_new(len, CryptoHeader_SIZE + 32, alloc);
     CString_strcpy(msg->bytes, x);
     msg->length = CString_strlen(x);
     msg->bytes[msg->length] = 0;
@@ -398,7 +398,7 @@ static void iteration(enum TestCa_Config cfg)
 int main()
 {
     iteration(TestCa_Config_OLD);
-    // iteration(TestCa_Config_OLD_NEW); TODO DISABLED TEST
+    iteration(TestCa_Config_OLD_NEW);
     //iteration(TestCa_Config_NOISE); TODO(cjd): re-enable this
     return 0;
 }

+ 4 - 4
crypto/test/CryptoAuth_unit_test.c

@@ -92,7 +92,7 @@ static void testHello(uint8_t* password, uint8_t* expectedOutput, enum TestCa_Co
     Assert_true(CString_strlen((char*)expectedOutput) == 264);
     struct Allocator* alloc = MallocAllocator_new(1<<20);
     struct Context* ctx = setUp(NULL, HERPUBKEY, password, alloc, cfg);
-    struct Message* msg = Message_new(0, CryptoHeader_SIZE + 12, alloc);
+    struct Message* msg = Message_new(0, CryptoHeader_SIZE + 32, alloc);
     Er_assert(Message_epush(msg, HELLOWORLD, HELLOWORLDLEN));
 
     Iface_send(&ctx->plaintext, msg);
@@ -133,7 +133,7 @@ static void receiveHelloWithNoAuth(enum TestCa_Config cfg)
         "847c0d2c375234f365e660955187a3735a0f7613d1609d3a6a4d8c53aeaa5a22", 64) > 0);
     struct Allocator* alloc = MallocAllocator_new(1<<20);
     struct Context* ctx = setUp(PRIVATEKEY, herPublic, NULL, alloc, cfg);
-    struct Message* msg = Message_new(132, 0, alloc);
+    struct Message* msg = Message_new(132, 32, alloc);
     Assert_true(Hex_decode(msg->bytes, msg->length,
         "0000000000ffffffffffffff7fffffffffffffffffffffffffffffffffffffff"
         "ffffffffffffffff847c0d2c375234f365e660955187a3735a0f7613d1609d3a"
@@ -162,7 +162,7 @@ static void repeatHello(enum TestCa_Config cfg)
 
     struct Allocator* alloc = MallocAllocator_new(1<<20);
     struct Context* ctx = setUp(NULL, HERPUBKEY, "password", alloc, cfg);
-    struct Message* msg = Message_new(0, CryptoHeader_SIZE + HELLOWORLDLEN, alloc);
+    struct Message* msg = Message_new(0, CryptoHeader_SIZE + HELLOWORLDLEN + 32, alloc);
     Er_assert(Message_epush(msg, HELLOWORLD, HELLOWORLDLEN));
 
     Iface_send(&ctx->plaintext, msg);
@@ -218,7 +218,7 @@ static void iteration(enum TestCa_Config cfg)
 int main()
 {
     iteration(TestCa_Config_OLD);
-    //iteration(TestCa_Config_OLD_NEW); // TODO(cjd): DISABLED TEST
+    iteration(TestCa_Config_OLD_NEW);
 
     // This will always fail because we are expecting particular results
     // which are specific to the old CryptoAuth

+ 85 - 10
crypto/test/TestCa.c

@@ -15,18 +15,21 @@
 #include "crypto/test/TestCa.h"
 #include "crypto/CryptoAuth.h"
 #include "rust/cjdns_sys/Rffi.h"
+#include "util/Hex.h"
 
 struct TestCa_s {
-    Rffi_CryptoAuth2_t* ca2;
+    RTypes_CryptoAuth2_t* ca2;
     struct CryptoAuth* ca;
     bool noise;
 };
 typedef struct TestCa_Session_pvt_s {
     TestCa_Session_t pub;
-    Rffi_CryptoAuth2_Session_t* s2;
+    RTypes_CryptoAuth2_Session_t* s2;
     struct CryptoAuth_Session* s;
     struct Iface sPlain;
     struct Iface sCipher;
+    struct Iface s2Plain;
+    struct Iface s2Cipher;
     Identity
 } TestCa_Session_pvt_t;
 
@@ -105,6 +108,12 @@ RTypes_StrList_t* TestCa_getUsers(const TestCa_t *ca, Allocator_t *alloc)
     return l1;
 }
 
+#define PASS 1
+#define STOP 2
+#define VERIFY 3
+
+#include <stdio.h>
+
 static Iface_DEFUN messagePlaintext(Message_t *msg, struct Iface* iface)
 {
     TestCa_Session_pvt_t* sess = Identity_containerOf(iface, TestCa_Session_pvt_t, pub.plaintext);
@@ -119,15 +128,23 @@ static Iface_DEFUN messagePlaintext(Message_t *msg, struct Iface* iface)
     }
     struct Error_s i1 = Error(NONE);
     if (sess->s) {
+        int flag = sess->s2 ? STOP : PASS;
+        Er_assert(Message_epushAd(msg, &flag, sizeof flag));
+        printf("Send [%d]\n", flag);
         i1 = Iface_send(&sess->sPlain, msg);
     }
     if (sess->s2) {
-        struct Error_s i2 = Error(NONE); // Iface_send(&sess->s2->internal, m2); TODO DISABLED
+        if (sess->s) {
+            Er_assert(Message_epushAd(m2, &msg, sizeof &msg));
+        }
+        int flag = sess->s ? VERIFY : PASS;
+        Er_assert(Message_epushAd(m2, &flag, sizeof flag));
+        printf("Send2 [%d]\n", flag);
+        struct Error_s i2 = Iface_send(&sess->s2Plain, m2);
         if (sess->s) {
             Assert_true(i2.e == i1.e);
-            Assert_true(msg->length == m2->length);
-            Assert_true(!Bits_memcmp(msg->bytes, m2->bytes, msg->length));
         }
+        printf("Send2 done\n");
         return i2;
     }
     return i1;
@@ -147,30 +164,84 @@ static Iface_DEFUN messageCiphertext(Message_t *msg, struct Iface* iface)
     }
     struct Error_s i1 = Error(NONE);
     if (sess->s) {
+        int flag = sess->s2 ? STOP : PASS;
+        Er_assert(Message_epushAd(msg, &flag, sizeof flag));
         i1 = Iface_send(&sess->sCipher, msg);
     }
     if (sess->s2) {
-        struct Error_s i2 = Error(NONE);//Rffi_CryptoAuth2_decrypt(sess->s2, m2); TODO DISABLED
+        int flag = PASS;
+        if (sess->s) {
+            uintptr_t mp = msg;
+            Er_assert(Message_epushAd(m2, &mp, sizeof &mp));
+            flag = VERIFY;
+        }
+        Er_assert(Message_epushAd(m2, &flag, sizeof flag));
+        struct Error_s i2 = Iface_send(&sess->s2Cipher, m2);
         if (sess->s) {
             Assert_true(i2.e == i1.e);
-            Assert_true(msg->length == m2->length);
-            Assert_true(!Bits_memcmp(msg->bytes, m2->bytes, msg->length));
         }
         return i2;
     }
     return i1;
 }
 
+static bool check(Message_t *msg, TestCa_Session_pvt_t* sess)
+{
+    int flag = 0;
+    Er_assert(Message_epopAd(msg, &flag, sizeof flag));
+    if (flag == PASS) {
+        printf("Passing message\n");
+    } else if (flag == STOP) {
+        // do nothing, wait for the next message to come through....
+        printf("Stopping message\n");
+        return true;
+    } else if (flag == VERIFY) {
+        uintptr_t m2p = 0;
+        Er_assert(Message_epopAd(msg, &m2p, sizeof m2p));
+        printf("Verifying message %x\n", m2p);
+        struct Message* m2 = (struct Message*) m2p;
+        if (msg->length != m2->length) {
+            Assert_failure("msg->length != m2->length: %d != %d",
+                msg->length, m2->length);
+        }
+        if (Bits_memcmp(msg->bytes, m2->bytes, msg->length)) {
+            const char* msgH = Hex_print(msg->bytes, msg->length, msg->alloc);
+            const char* m2H = Hex_print(m2->bytes, m2->length, m2->alloc);
+            Assert_failure("msg->bytes != m2->bytes:\n%s\n%s\n", msgH, m2H);
+        }
+        Assert_true(!Bits_memcmp(msg->bytes, m2->bytes, msg->length));
+    } else {
+        Assert_failure("unexpected flag [%d]", flag);
+    }
+    return false;
+}
+
 static Iface_DEFUN sPlainRecv(Message_t *msg, struct Iface* iface)
 {
     TestCa_Session_pvt_t* sess = Identity_containerOf(iface, TestCa_Session_pvt_t, sPlain);
-    Iface_next(&sess->pub.plaintext, msg);
+    if (check(msg, sess)) { return Error(NONE); }
+    return Iface_next(&sess->pub.plaintext, msg);
+}
+
+static Iface_DEFUN s2PlainRecv(Message_t *msg, struct Iface* iface)
+{
+    TestCa_Session_pvt_t* sess = Identity_containerOf(iface, TestCa_Session_pvt_t, s2Plain);
+    if (check(msg, sess)) { return Error(NONE); }
+    return Iface_next(&sess->pub.plaintext, msg);
 }
 
 static Iface_DEFUN sCipherRecv(Message_t *msg, struct Iface* iface)
 {
     TestCa_Session_pvt_t* sess = Identity_containerOf(iface, TestCa_Session_pvt_t, sCipher);
-    Iface_next(&sess->pub.ciphertext, msg);
+    if (check(msg, sess)) { return Error(NONE); }
+    return Iface_next(&sess->pub.ciphertext, msg);
+}
+
+static Iface_DEFUN s2CipherRecv(Message_t *msg, struct Iface* iface)
+{
+    TestCa_Session_pvt_t* sess = Identity_containerOf(iface, TestCa_Session_pvt_t, s2Cipher);
+    if (check(msg, sess)) { return Error(NONE); }
+    return Iface_next(&sess->pub.ciphertext, msg);
 }
 
 TestCa_Session_t* TestCa_newSession(
@@ -185,6 +256,8 @@ TestCa_Session_t* TestCa_newSession(
     Identity_set(out);
     out->sCipher.send = sCipherRecv;
     out->sPlain.send = sPlainRecv;
+    out->s2Cipher.send = s2CipherRecv;
+    out->s2Plain.send = s2PlainRecv;
     if (ca->ca) {
         out->s = CryptoAuth_newSession(ca->ca, alloc, herPublicKey, requireAuth, name);
         Iface_plumb(&out->sCipher, &out->s->ciphertext);
@@ -193,6 +266,8 @@ TestCa_Session_t* TestCa_newSession(
     if (ca->ca2) {
         out->s2 = Rffi_CryptoAuth2_newSession(
             ca->ca2, alloc, herPublicKey, requireAuth, name, ca->noise && useNoise);
+        Iface_plumb(&out->s2Cipher, out->s2->ciphertext);
+        Iface_plumb(&out->s2Plain, out->s2->plaintext);
     }
     out->pub.plaintext.send = messagePlaintext;
     out->pub.ciphertext.send = messageCiphertext;

+ 1 - 3
net/InterfaceController.c

@@ -533,15 +533,13 @@ static int closeInterface(struct Allocator_OnFreeJob* job)
     struct Peer* toClose = Identity_check((struct Peer*) job->userData);
 
     int index = Map_EndpointsBySockaddr_indexForHandle(toClose->handle, &toClose->ici->peerMap);
-    if (index < 0) {
+    if (index < 0 || toClose->ici->peerMap.values[index] != toClose) {
         // Happens if the ep was created as a result of handleUnexpectedIncoming
         return 0;
     }
     sendPeer(0xffffffff, PFChan_Core_PEER_GONE, toClose, 0xffff);
     Log_debug(toClose->ici->ic->logger,
         "Closing interface [%d] with handle [%u]", index, toClose->handle);
-    Assert_true(index >= 0);
-    Assert_true(toClose->ici->peerMap.values[index] == toClose);
     Map_EndpointsBySockaddr_remove(index, &toClose->ici->peerMap);
     return 0;
 }

+ 6 - 0
rust/cjdns_sys/RTypes.h

@@ -62,11 +62,17 @@ typedef struct {
   uint64_t duplicate_packets;
 } RTypes_CryptoStats_t;
 
+typedef struct {
+  Iface_t *plaintext;
+  Iface_t *ciphertext;
+} RTypes_CryptoAuth2_Session_t;
+
 typedef struct {
   RTypes_IfWrapper_t a;
   RTypes_StrList_t b;
   RTypes_CryptoAuth_State_t c;
   RTypes_CryptoStats_t d;
+  RTypes_CryptoAuth2_Session_t e;
 } RTypes_ExportMe;
 
 #endif /* RTypes_H */

+ 22 - 24
rust/cjdns_sys/Rffi.h

@@ -5,9 +5,7 @@
 
 #include "RffiPrefix.h"
 
-typedef struct Rffi_CryptoAuth2_Session_t Rffi_CryptoAuth2_Session_t;
-
-typedef struct Rffi_CryptoAuth2_t Rffi_CryptoAuth2_t;
+typedef struct RTypes_CryptoAuth2_t RTypes_CryptoAuth2_t;
 
 RTypes_IfWrapper_t Rffi_testwrapper_create(Allocator_t *a);
 
@@ -16,42 +14,42 @@ RTypes_IfWrapper_t Rffi_android_create(Allocator_t *a);
 int Rffi_CryptoAuth2_addUser_ipv6(String_t *password,
                                   String_t *login,
                                   uint8_t *ipv6,
-                                  Rffi_CryptoAuth2_t *ca);
+                                  RTypes_CryptoAuth2_t *ca);
 
-int Rffi_CryptoAuth2_removeUsers(Rffi_CryptoAuth2_t *context, String_t *user);
+int Rffi_CryptoAuth2_removeUsers(RTypes_CryptoAuth2_t *context, String_t *user);
 
-RTypes_StrList_t *Rffi_CryptoAuth2_getUsers(const Rffi_CryptoAuth2_t *ca, Allocator_t *alloc);
+RTypes_StrList_t *Rffi_CryptoAuth2_getUsers(const RTypes_CryptoAuth2_t *ca, Allocator_t *alloc);
 
-Rffi_CryptoAuth2_t *Rffi_CryptoAuth2_new(Allocator_t *allocator,
-                                         const uint8_t *privateKey,
-                                         Random_t *random);
+RTypes_CryptoAuth2_t *Rffi_CryptoAuth2_new(Allocator_t *allocator,
+                                           const uint8_t *privateKey,
+                                           Random_t *random);
 
-Rffi_CryptoAuth2_Session_t *Rffi_CryptoAuth2_newSession(Rffi_CryptoAuth2_t *ca,
-                                                        Allocator_t *alloc,
-                                                        const uint8_t *herPublicKey,
-                                                        bool requireAuth,
-                                                        char *name,
-                                                        bool useNoise);
+RTypes_CryptoAuth2_Session_t *Rffi_CryptoAuth2_newSession(RTypes_CryptoAuth2_t *ca,
+                                                          Allocator_t *alloc,
+                                                          const uint8_t *herPublicKey,
+                                                          bool requireAuth,
+                                                          char *name,
+                                                          bool useNoise);
 
 void Rffi_CryptoAuth2_setAuth(const String_t *password,
                               const String_t *login,
-                              Rffi_CryptoAuth2_Session_t *caSession);
+                              RTypes_CryptoAuth2_Session_t *caSession);
 
-void Rffi_CryptoAuth2_resetIfTimeout(Rffi_CryptoAuth2_Session_t *session);
+void Rffi_CryptoAuth2_resetIfTimeout(RTypes_CryptoAuth2_Session_t *session);
 
-void Rffi_CryptoAuth2_reset(Rffi_CryptoAuth2_Session_t *caSession);
+void Rffi_CryptoAuth2_reset(RTypes_CryptoAuth2_Session_t *caSession);
 
-RTypes_CryptoAuth_State_t Rffi_CryptoAuth2_getState(Rffi_CryptoAuth2_Session_t *session);
+RTypes_CryptoAuth_State_t Rffi_CryptoAuth2_getState(RTypes_CryptoAuth2_Session_t *session);
 
-void Rffi_CryptoAuth2_getHerPubKey(const Rffi_CryptoAuth2_Session_t *session, uint8_t *pkOut);
+void Rffi_CryptoAuth2_getHerPubKey(const RTypes_CryptoAuth2_Session_t *session, uint8_t *pkOut);
 
-void Rffi_CryptoAuth2_getHerIp6(const Rffi_CryptoAuth2_Session_t *session, uint8_t *ipOut);
+void Rffi_CryptoAuth2_getHerIp6(const RTypes_CryptoAuth2_Session_t *session, uint8_t *ipOut);
 
-String_t *Rffi_CryptoAuth2_getName(const Rffi_CryptoAuth2_Session_t *session, Allocator_t *alloc);
+String_t *Rffi_CryptoAuth2_getName(const RTypes_CryptoAuth2_Session_t *session, Allocator_t *alloc);
 
-void Rffi_CryptoAuth2_getPubKey(Rffi_CryptoAuth2_t *ca, uint8_t *pkOut);
+void Rffi_CryptoAuth2_getPubKey(RTypes_CryptoAuth2_t *ca, uint8_t *pkOut);
 
-void Rffi_CryptoAuth2_stats(const Rffi_CryptoAuth2_Session_t *session,
+void Rffi_CryptoAuth2_stats(const RTypes_CryptoAuth2_Session_t *session,
                             RTypes_CryptoStats_t *statsOut);
 
 void Rffi_panic(const char *msg);

+ 103 - 88
rust/cjdns_sys/src/crypto/crypto_auth.rs

@@ -1,6 +1,5 @@
 //! CryptoAuth
 
-use std::convert::TryFrom;
 use std::str::FromStr;
 use std::sync::Arc;
 
@@ -13,7 +12,7 @@ use thiserror::Error;
 
 use crate::bytestring::ByteString;
 use crate::crypto::crypto_header::{AuthType, Challenge, CryptoHeader};
-use crate::crypto::keys::{IpV6, PrivateKey, PublicKey};
+use crate::crypto::keys::{PrivateKey, PublicKey};
 use crate::crypto::random::Random;
 use crate::crypto::replay_protector::ReplayProtector;
 use crate::crypto::utils::{crypto_hash_sha256, crypto_scalarmult_curve25519_base};
@@ -346,7 +345,7 @@ impl CryptoAuth {
         } else {
             debug!("Flushing [{}] users", count);
         }
-        return count;
+        count
     }
 
     /// Get a list of all the users' logins.
@@ -427,17 +426,18 @@ impl SessionMut {
     }
 
     fn get_her_pubkey(&self) -> [u8; 32] {
-        self.her_public_key.raw().clone()
+        *self.her_public_key.raw()
     }
 
     fn get_her_ip6(&self) -> [u8; 16] {
-        self.her_ip6.clone()
+        self.her_ip6
     }
 
     fn get_name(&self) -> Option<String> {
         self.display_name.clone()
     }
 
+    #[allow(clippy::if_same_then_else)]
     fn reset_if_timeout(&mut self, event_base: &EventBase) {
         if self.next_nonce == State::SentHello as u32 {
             // Lets not reset the session, we just sent one or more hello packets and
@@ -451,10 +451,8 @@ impl SessionMut {
         let delta = now_secs - time_of_last_packet;
         if delta < self.setup_reset_after_inactivity_seconds as i64 {
             return;
-        } else if delta < self.reset_after_inactivity_seconds as i64 {
-            if self.established {
-                return;
-            }
+        } else if delta < self.reset_after_inactivity_seconds as i64 && self.established {
+            return;
         }
 
         debug::log(self, || {
@@ -525,7 +523,7 @@ impl SessionMut {
         encrypt(
             session.next_nonce,
             msg,
-            session.shared_secret.clone(),
+            session.shared_secret,
             session.is_initiator,
         );
 
@@ -611,7 +609,7 @@ impl SessionMut {
         } else if nonce >= Nonce::FirstTrafficPacket as u32 {
             debug_assert!(!session.shared_secret.is_zero());
 
-            let ret = session.decrypt_message(nonce, msg, session.shared_secret.clone(), sess);
+            let ret = session.decrypt_message(nonce, msg, session.shared_secret, sess);
             match ret {
                 Ok(_) => {
                     let mut session = RwLockUpgradableReadGuard::upgrade(session);
@@ -623,7 +621,7 @@ impl SessionMut {
                     debug::log(&session, || {
                         format!("DROP Failed to decrypt message [{}]", err)
                     });
-                    return Err(err.into());
+                    Err(err)
                 }
             }
         } else if nonce <= Nonce::RepeatHello as u32 {
@@ -645,7 +643,7 @@ impl SessionMut {
                     nonce
                 )
             });
-            return Err(DecryptError::DecryptErr(DecryptErr::KeyPktEstablishedSession).into());
+            Err(DecryptError::DecryptErr(DecryptErr::KeyPktEstablishedSession).into())
         }
     }
 
@@ -675,7 +673,7 @@ impl SessionMut {
         let header = msg.peek_mut::<CryptoHeader>().unwrap();
 
         // Set the permanent key
-        header.public_key = context.public_key.raw().clone();
+        header.public_key = *context.public_key.raw();
 
         ensure!(self.her_key_known(), EncryptError);
 
@@ -701,9 +699,9 @@ impl SessionMut {
             context.rand.random_bytes(&mut self.our_temp_priv_key);
             self.our_temp_pub_key = {
                 //TODO Likely to be simplified after using proper types everywhere
-                let priv_key = PrivateKey::from(self.our_temp_priv_key.clone());
+                let priv_key = PrivateKey::from(self.our_temp_priv_key);
                 let pub_key = crypto_scalarmult_curve25519_base(&priv_key);
-                pub_key.raw().clone()
+                *pub_key.raw()
             };
 
             if CryptoAuth::LOG_KEYS {
@@ -748,8 +746,8 @@ impl SessionMut {
         let shared_secret;
         if self.next_nonce < State::ReceivedHello as u32 {
             shared_secret = get_shared_secret(
-                context.private_key.raw().clone(),
-                self.her_public_key.raw().clone(),
+                *context.private_key.raw(),
+                *self.her_public_key.raw(),
                 password_hash,
             );
 
@@ -762,7 +760,7 @@ impl SessionMut {
             // her_temp_pub_key was set by decrypt_handshake()
             debug_assert!(!self.her_temp_pub_key.is_zero());
             shared_secret = get_shared_secret(
-                context.private_key.raw().clone(),
+                *context.private_key.raw(),
                 self.her_temp_pub_key,
                 password_hash,
             );
@@ -788,7 +786,7 @@ impl SessionMut {
         // Temporarily remove CryptoHeader until the encrypted_temp_key field.
         let mut saved = msg.pop_bytes(CryptoHeader::SIZE - 32).expect("pop");
 
-        encrypt_rnd_nonce(handshake_nonce.clone(), msg, shared_secret);
+        encrypt_rnd_nonce(handshake_nonce, msg, shared_secret);
 
         if CryptoAuth::LOG_KEYS {
             debug!(
@@ -897,8 +895,8 @@ impl SessionMut {
             });
 
             shared_secret = get_shared_secret(
-                sess.context.private_key.raw().clone(),
-                self.her_public_key.raw().clone(),
+                *sess.context.private_key.raw(),
+                *self.her_public_key.raw(),
                 password_hash,
             );
 
@@ -918,8 +916,8 @@ impl SessionMut {
 
             // We sent the hello, this is a key
             shared_secret = get_shared_secret(
-                self.our_temp_priv_key.clone(),
-                self.her_public_key.raw().clone(),
+                self.our_temp_priv_key,
+                *self.her_public_key.raw(),
                 password_hash,
             );
 
@@ -945,7 +943,7 @@ impl SessionMut {
         }
 
         // Decrypt her temp public key and the message.
-        let r = decrypt_rnd_nonce(header.handshake_nonce.clone(), msg, shared_secret);
+        let r = decrypt_rnd_nonce(header.handshake_nonce, msg, shared_secret);
         if r.is_err() {
             header.wipe(); // Just in case
             debug::log(self, || {
@@ -1170,13 +1168,43 @@ fn ip6_from_key(key: &[u8; 32]) -> [u8; 16] {
 pub struct PlaintextRecv(Arc<Session>);
 impl IfRecv for PlaintextRecv {
     fn recv(&self, m: &mut Message) -> Result<()> {
-        self.0.encrypt(m)
+        println!("Encrypt");
+        self.0.encrypt(m)?;
+        self.0.cipher_pvt.send(m)
     }
 }
 pub struct CiphertextRecv(Arc<Session>);
 impl IfRecv for CiphertextRecv {
     fn recv(&self, m: &mut Message) -> Result<()> {
-        self.0.decrypt(m)
+        let mut first16 = [0_u8; 16];
+        first16.copy_from_slice(m.peek_bytes(16)?);
+        match self.0.decrypt(m) {
+            Ok(()) => {
+                m.push(0_u32)?;
+                self.0.plain_pvt.send(m)
+            }
+            Err(e) => {
+                println!("Error decrypting {} {}", e, m.len());
+                let ee = match e.downcast_ref::<DecryptError>() {
+                    Some(ee) => match ee {
+                        DecryptError::DecryptErr(ee) => ee,
+                        DecryptError::Internal(_) => {
+                            return Err(e);
+                        }
+                    },
+                    None => {
+                        return Err(e);
+                    }
+                }
+                .clone() as u32;
+                m.clear();
+                m.push((self.0.get_state() as u32).to_be())?;
+                m.push(ee.to_be())?;
+                m.push_bytes(&first16)?;
+                m.push(ee)?;
+                self.0.plain_pvt.send(m)
+            }
+        }
     }
 }
 
@@ -1379,12 +1407,12 @@ impl Session {
             TunnResult::Done => {
                 // This means we need to return empty buffer
                 msg.clear();
-                return Ok(());
+                Ok(())
             }
             TunnResult::WriteToNetwork(buf) => {
                 msg.clear();
                 msg.push_bytes(buf).expect("msg size");
-                return Ok(());
+                Ok(())
             }
             bad => unreachable!("unexpected TunnResult: {:?}", bad),
         }
@@ -1700,6 +1728,7 @@ mod tests {
     use crate::cffi;
     use crate::crypto::crypto_auth::Session;
     use crate::crypto::random::Random;
+    use crate::external::interface::iface::Iface;
     use crate::interface::wire::message::Message;
     use crate::util::events::EventBase;
 
@@ -1770,7 +1799,7 @@ mod tests {
             my_priv_key: PrivateKey,
             her_pub_key: PublicKey,
             name: &str,
-        ) -> Arc<super::Session> {
+        ) -> (Arc<super::Session>, Iface, Iface) {
             let ca = super::CryptoAuth::new(Some(my_priv_key), EventBase {}, Random::Fake);
             let ca = Arc::new(ca);
 
@@ -1782,17 +1811,17 @@ mod tests {
             assert_eq!(res.err(), None);
 
             let sess = super::Session::new(
-                ca.clone(),
+                ca,
                 her_pub_key,
                 false,
                 Some(format!("{}'s session", name)),
                 false,
             );
-            assert_eq!(sess.as_ref().err(), None);
+            assert!(sess.is_ok());
             sess.unwrap()
         }
 
-        let my_session = mk_sess(
+        let (my_session, my_plain, my_cipher) = mk_sess(
             my_keys.private_key.clone(),
             her_keys.public_key.clone(),
             "bob",
@@ -1803,17 +1832,14 @@ mod tests {
         let orig_length = msg.len();
 
         let res = my_session.encrypt(&mut msg);
-        assert_eq!(res.err(), None);
+        assert!(res.is_ok());
         assert_ne!(msg.len(), orig_length);
 
-        let her_session = mk_sess(
-            her_keys.private_key.clone(),
-            my_keys.public_key.clone(),
-            "alice",
-        );
+        let (her_session, her_plain, her_cipher) =
+            mk_sess(her_keys.private_key, my_keys.public_key, "alice");
 
         let res = her_session.decrypt(&mut msg);
-        assert_eq!(res.err(), None);
+        assert!(res.is_ok());
         assert_eq!(msg.len(), orig_length);
         assert_eq!(msg.bytes(), b"HelloWorld012345");
     }
@@ -1828,7 +1854,7 @@ mod tests {
             my_priv_key: PrivateKey,
             her_pub_key: PublicKey,
             name: &str,
-        ) -> Arc<super::Session> {
+        ) -> (Arc<super::Session>, Iface, Iface) {
             let ca = super::CryptoAuth::new(Some(my_priv_key), EventBase {}, Random::Fake);
             let ca = Arc::new(ca);
 
@@ -1840,13 +1866,13 @@ mod tests {
             assert_eq!(res.err(), None);
 
             let sess = super::Session::new(
-                ca.clone(),
+                ca,
                 her_pub_key,
                 true,
                 Some(format!("{}'s session", name)),
                 false,
             );
-            assert_eq!(sess.as_ref().err(), None);
+            assert!(sess.is_ok());
             sess.unwrap()
         }
 
@@ -1857,7 +1883,7 @@ mod tests {
             );
         }
 
-        let my_session = mk_sess(
+        let (my_session, my_plain, my_cipher) = mk_sess(
             my_keys.private_key.clone(),
             her_keys.public_key.clone(),
             "bob",
@@ -1869,18 +1895,15 @@ mod tests {
         let orig_length = msg.len();
 
         let res = my_session.encrypt(&mut msg);
-        assert_eq!(res.err(), None);
+        assert!(res.is_ok());
         assert_ne!(msg.len(), orig_length);
 
-        let her_session = mk_sess(
-            her_keys.private_key.clone(),
-            my_keys.public_key.clone(),
-            "alice",
-        );
+        let (her_session, her_plain, her_cipher) =
+            mk_sess(her_keys.private_key, my_keys.public_key, "alice");
         set_auth(&her_session, "bob");
 
         let res = her_session.decrypt(&mut msg);
-        assert_eq!(res.err(), None);
+        assert!(res.is_ok());
         assert_eq!(msg.len(), orig_length);
         assert_eq!(msg.bytes(), b"HelloWorld012345");
     }
@@ -1891,7 +1914,7 @@ mod tests {
         let my_keys = keys_api.key_pair();
         let her_keys = keys_api.key_pair();
 
-        let rust_session = {
+        let (rust_session, rust_plain, rust_cipher) = {
             let priv_key = my_keys.private_key.clone();
             let pub_key = her_keys.public_key.clone();
             let name = "bob";
@@ -1908,13 +1931,13 @@ mod tests {
             assert_eq!(res.err(), None);
 
             let sess = super::Session::new(
-                ca.clone(),
+                ca,
                 pub_key,
                 false,
                 Some(format!("{}'s session", name)),
                 false,
             );
-            assert_eq!(sess.as_ref().err(), None);
+            assert!(sess.is_ok());
             sess.unwrap()
         };
 
@@ -1923,12 +1946,12 @@ mod tests {
         let orig_length = msg.len();
 
         let res = rust_session.encrypt(&mut msg);
-        assert_eq!(res.err(), None);
+        assert!(res.is_ok());
         assert_ne!(msg.len(), orig_length);
 
         let c_session = {
-            let priv_key = her_keys.private_key.clone();
-            let pub_key = my_keys.public_key.clone();
+            let priv_key = her_keys.private_key;
+            let pub_key = my_keys.public_key;
             let name = "alice";
 
             let alloc = unsafe {
@@ -1954,7 +1977,7 @@ mod tests {
             };
             assert_eq!(res, 0, "CryptoAuth_addUser_ipv6() failed: {}", res);
 
-            let sess = unsafe {
+            unsafe {
                 cffi::CryptoAuth_newSession(
                     ca,
                     alloc,
@@ -1962,9 +1985,7 @@ mod tests {
                     false,
                     format!("{}'s session", name).as_mut_ptr() as *mut i8,
                 )
-            };
-
-            sess
+            }
         };
 
         let res = unsafe { cffi::CryptoAuth_decrypt(c_session, msg.as_c_message()) };
@@ -2007,7 +2028,7 @@ mod tests {
             };
             assert_eq!(res, 0, "CryptoAuth_addUser_ipv6() failed: {}", res);
 
-            let sess = unsafe {
+            unsafe {
                 cffi::CryptoAuth_newSession(
                     ca,
                     alloc,
@@ -2015,9 +2036,7 @@ mod tests {
                     false,
                     format!("{}'s session", name).as_mut_ptr() as *mut i8,
                 )
-            };
-
-            sess
+            }
         };
 
         let mut msg = mk_msg(256);
@@ -2028,9 +2047,9 @@ mod tests {
         assert_eq!(res, 0);
         assert_ne!(msg.len(), orig_length);
 
-        let rust_session = {
-            let priv_key = her_keys.private_key.clone();
-            let pub_key = my_keys.public_key.clone();
+        let (rust_session, rust_plain, rust_cipher) = {
+            let priv_key = her_keys.private_key;
+            let pub_key = my_keys.public_key;
             let name = "alice";
 
             let ca =
@@ -2045,18 +2064,18 @@ mod tests {
             assert_eq!(res.err(), None);
 
             let sess = super::Session::new(
-                ca.clone(),
+                ca,
                 pub_key,
                 false,
                 Some(format!("{}'s session", name)),
                 false,
             );
-            assert_eq!(sess.as_ref().err(), None);
+            assert!(sess.is_ok());
             sess.unwrap()
         };
 
         let res = rust_session.decrypt(&mut msg);
-        assert_eq!(res.err(), None);
+        assert!(res.is_ok());
         assert_eq!(msg.len(), orig_length);
         assert_eq!(msg.bytes(), b"HelloWorld012345");
     }
@@ -2080,7 +2099,7 @@ mod tests {
             my_priv_key: PrivateKey,
             her_pub_key: PublicKey,
             name: &str,
-        ) -> Arc<super::Session> {
+        ) -> (Arc<super::Session>, Iface, Iface) {
             let ca = super::CryptoAuth::new(Some(my_priv_key), EventBase {}, Random::Fake);
             let ca = Arc::new(ca);
 
@@ -2092,52 +2111,48 @@ mod tests {
             assert_eq!(res.err(), None);
 
             let sess = super::Session::new(
-                ca.clone(),
+                ca,
                 her_pub_key,
                 false,
                 Some(format!("{}'s session", name)),
                 true,
             );
-            assert_eq!(sess.as_ref().err(), None);
             sess.unwrap()
         }
 
-        let her_session = mk_sess(
+        let (her_session, her_plain, her_cipher) = mk_sess(
             her_keys.private_key.clone(),
             my_keys.public_key.clone(),
             "alice",
         );
 
-        let my_session = mk_sess(
-            my_keys.private_key.clone(),
-            her_keys.public_key.clone(),
-            "bob",
-        );
+        let (my_session, my_plain, my_cipher) =
+            mk_sess(my_keys.private_key, her_keys.public_key, "bob");
 
         let mut msg = mk_msg(1024);
         msg.push_bytes(b"Hello World").unwrap();
         let orig_length = msg.len();
 
         let res = my_session.encrypt(&mut msg);
-        assert_eq!(res.err(), None);
+        assert!(res.is_ok());
         assert_ne!(msg.len(), orig_length);
 
-        let res = Session::tun_recv(&her_session.tunnel.unwrap(), &mut msg);
-        assert_eq!(res.as_ref().err(), None);
-        if let Some(Some(send_back)) = res.ok() {
+        let res = Session::tun_recv(her_session.tunnel.as_ref().unwrap(), &mut msg);
+        assert!(res.is_ok());
+        if let Ok(Some(send_back)) = res {
             'outer: for packet in send_back {
                 msg.clear();
                 msg.push_bytes(&packet).expect("msg size");
-                let res = Session::tun_recv(&my_session.tunnel.unwrap(), &mut msg);
-                assert_eq!(res.as_ref().err(), None);
+                let res = Session::tun_recv(my_session.tunnel.as_ref().unwrap(), &mut msg);
+                assert!(res.is_ok());
                 assert_eq!(msg.len(), 0);
 
-                if let Some(Some(send_back)) = res.ok() {
+                if let Ok(Some(send_back)) = res {
                     for packet in send_back {
                         msg.clear();
                         msg.push_bytes(&packet).expect("msg size");
                         let res = her_session.decrypt(&mut msg);
-                        assert_eq!(res, Ok(None));
+                        assert!(res.is_ok());
                         if msg.len() > 0 {
                             break 'outer;
                         }

+ 52 - 35
rust/cjdns_sys/src/rffi.rs

@@ -34,13 +34,6 @@ pub unsafe extern "C" fn Rffi_android_create(a: *mut Allocator_t) -> RTypes_IfWr
     }
 }
 
-pub struct Rffi_CryptoAuth2_t(Arc<crypto_auth::CryptoAuth>);
-pub struct Rffi_CryptoAuth2_Session_t {
-    s: Arc<crypto_auth::Session>,
-    pub plaintext: *mut cffi::Iface_t,
-    pub ciphertext: *mut cffi::Iface_t,
-}
-
 unsafe fn cu8(s: *const u8, len: usize) -> Vec<u8> {
     std::slice::from_raw_parts::<u8>(s, len).to_vec()
 }
@@ -62,12 +55,20 @@ unsafe fn strc(alloc: *mut Allocator_t, s: ByteString) -> *mut String_t {
     allocator::adopt(alloc, String_t { len, bytes })
 }
 
+#[repr(C)]
+pub struct Rffi_CryptoAuth2_Session_t {
+    r: RTypes_CryptoAuth2_Session_t,
+    s: Arc<crypto_auth::Session>,
+}
+
+pub struct RTypes_CryptoAuth2_t(pub Arc<crypto_auth::CryptoAuth>);
+
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_addUser_ipv6(
     password: *mut String_t,
     login: *mut String_t,
     ipv6: *mut u8,
-    ca: *mut Rffi_CryptoAuth2_t,
+    ca: *mut RTypes_CryptoAuth2_t,
 ) -> c_int {
     let ip6 = if ipv6.is_null() {
         None
@@ -89,7 +90,7 @@ pub unsafe extern "C" fn Rffi_CryptoAuth2_addUser_ipv6(
 
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_removeUsers(
-    context: *mut Rffi_CryptoAuth2_t,
+    context: *mut RTypes_CryptoAuth2_t,
     user: *mut String_t,
 ) -> c_int {
     (*context).0.remove_users(cstr(user)) as c_int
@@ -97,7 +98,7 @@ pub unsafe extern "C" fn Rffi_CryptoAuth2_removeUsers(
 
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_getUsers(
-    ca: *const Rffi_CryptoAuth2_t,
+    ca: *const RTypes_CryptoAuth2_t,
     alloc: *mut Allocator_t,
 ) -> *mut RTypes_StrList_t {
     let mut users = (*ca).0.get_users();
@@ -115,10 +116,10 @@ pub unsafe extern "C" fn Rffi_CryptoAuth2_new(
     allocator: *mut Allocator_t,
     privateKey: *const u8,
     random: *mut Random_t,
-) -> *mut Rffi_CryptoAuth2_t {
+) -> *mut RTypes_CryptoAuth2_t {
     allocator::adopt(
         allocator,
-        Rffi_CryptoAuth2_t(Arc::new(crypto_auth::CryptoAuth::new(
+        RTypes_CryptoAuth2_t(Arc::new(crypto_auth::CryptoAuth::new(
             if privateKey.is_null() {
                 None
             } else {
@@ -135,13 +136,13 @@ pub unsafe extern "C" fn Rffi_CryptoAuth2_new(
 
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_newSession(
-    ca: *mut Rffi_CryptoAuth2_t,
+    ca: *mut RTypes_CryptoAuth2_t,
     alloc: *mut Allocator_t,
     herPublicKey: *const u8,
     requireAuth: bool,
     name: *mut c_char,
     useNoise: bool,
-) -> *mut Rffi_CryptoAuth2_Session_t {
+) -> *mut RTypes_CryptoAuth2_Session_t {
     let (session, plaintext, ciphertext) = crypto_auth::Session::new(
         Arc::clone(&(*ca).0),
         {
@@ -161,83 +162,99 @@ pub unsafe extern "C" fn Rffi_CryptoAuth2_newSession(
         useNoise,
     )
     .expect("bad public key"); //TODO Pass the error to C code somehow instead of `expect()`.
-    allocator::adopt(
+    &mut allocator::adopt(
         alloc,
         Rffi_CryptoAuth2_Session_t {
+            r: RTypes_CryptoAuth2_Session_t {
+                ciphertext: cif::wrap(alloc, ciphertext),
+                plaintext: cif::wrap(alloc, plaintext),
+            },
             s: session,
-            ciphertext: cif::wrap(alloc, ciphertext),
-            plaintext: cif::wrap(alloc, plaintext),
         },
     )
+    .r as *mut _
+}
+
+unsafe fn ffi_sess_mut(
+    s: *mut RTypes_CryptoAuth2_Session_t,
+) -> &'static mut Rffi_CryptoAuth2_Session_t {
+    &mut *(s as *mut Rffi_CryptoAuth2_Session_t)
+}
+unsafe fn ffi_sess(s: *const RTypes_CryptoAuth2_Session_t) -> &'static Rffi_CryptoAuth2_Session_t {
+    &*(s as *const Rffi_CryptoAuth2_Session_t)
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_setAuth(
     password: *const String_t,
     login: *const String_t,
-    caSession: *mut Rffi_CryptoAuth2_Session_t,
+    caSession: *mut RTypes_CryptoAuth2_Session_t,
 ) {
-    (*caSession).s.set_auth(cstr(password), cstr(login))
+    ffi_sess_mut(caSession)
+        .s
+        .set_auth(cstr(password), cstr(login))
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn Rffi_CryptoAuth2_resetIfTimeout(session: *mut Rffi_CryptoAuth2_Session_t) {
-    (*session).s.reset_if_timeout()
+pub unsafe extern "C" fn Rffi_CryptoAuth2_resetIfTimeout(
+    session: *mut RTypes_CryptoAuth2_Session_t,
+) {
+    ffi_sess_mut(session).s.reset_if_timeout()
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn Rffi_CryptoAuth2_reset(caSession: *mut Rffi_CryptoAuth2_Session_t) {
-    (*caSession).s.reset()
+pub unsafe extern "C" fn Rffi_CryptoAuth2_reset(caSession: *mut RTypes_CryptoAuth2_Session_t) {
+    ffi_sess_mut(caSession).s.reset()
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_getState(
-    session: *mut Rffi_CryptoAuth2_Session_t,
+    session: *mut RTypes_CryptoAuth2_Session_t,
 ) -> RTypes_CryptoAuth_State_t {
-    (*session).s.get_state()
+    ffi_sess_mut(session).s.get_state()
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_getHerPubKey(
-    session: *const Rffi_CryptoAuth2_Session_t,
+    session: *const RTypes_CryptoAuth2_Session_t,
     pkOut: *mut u8,
 ) {
-    let p = (*session).s.get_her_pubkey();
+    let p = ffi_sess(session).s.get_her_pubkey();
     std::slice::from_raw_parts_mut(pkOut, 32).copy_from_slice(&p[..]);
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_getHerIp6(
-    session: *const Rffi_CryptoAuth2_Session_t,
+    session: *const RTypes_CryptoAuth2_Session_t,
     ipOut: *mut u8,
 ) {
-    let p = (*session).s.get_her_ip6();
+    let p = ffi_sess(session).s.get_her_ip6();
     std::slice::from_raw_parts_mut(ipOut, 16).copy_from_slice(&p[..]);
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_getName(
-    session: *const Rffi_CryptoAuth2_Session_t,
+    session: *const RTypes_CryptoAuth2_Session_t,
     alloc: *mut Allocator_t,
 ) -> *mut String_t {
-    match (*session).s.get_name() {
-        None => 0 as *mut String_t,
+    match ffi_sess(session).s.get_name() {
+        None => std::ptr::null_mut::<String_t>(),
         Some(name) => strc(alloc, ByteString::from(name)),
     }
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn Rffi_CryptoAuth2_getPubKey(ca: *mut Rffi_CryptoAuth2_t, pkOut: *mut u8) {
+pub unsafe extern "C" fn Rffi_CryptoAuth2_getPubKey(ca: *mut RTypes_CryptoAuth2_t, pkOut: *mut u8) {
     let p = (*ca).0.public_key.raw();
     std::slice::from_raw_parts_mut(pkOut, 32).copy_from_slice(&p[..]);
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_stats(
-    session: *const Rffi_CryptoAuth2_Session_t,
+    session: *const RTypes_CryptoAuth2_Session_t,
     statsOut: *mut RTypes_CryptoStats_t,
 ) {
-    let st = (*session).s.stats();
+    let st = ffi_sess(session).s.stats();
     (*statsOut) = st;
 }
 

+ 11 - 1
rust/cjdns_sys/src/rtypes.rs

@@ -1,6 +1,9 @@
 #![allow(non_snake_case)]
 #![allow(non_camel_case_types)]
-use crate::cffi::{Iface_t, String_t};
+use std::sync::Arc;
+
+use crate::cffi::{self, Iface_t, String_t};
+use crate::crypto::crypto_auth;
 
 #[repr(C)]
 #[derive(Debug, Copy, Clone)]
@@ -54,6 +57,12 @@ pub struct RTypes_CryptoStats_t {
     pub duplicate_packets: u64,
 }
 
+#[repr(C)]
+pub struct RTypes_CryptoAuth2_Session_t {
+    pub plaintext: *mut cffi::Iface_t,
+    pub ciphertext: *mut cffi::Iface_t,
+}
+
 #[allow(dead_code)]
 #[repr(C)]
 pub struct RTypes_ExportMe {
@@ -61,4 +70,5 @@ pub struct RTypes_ExportMe {
     b: RTypes_StrList_t,
     c: RTypes_CryptoAuth_State_t,
     d: RTypes_CryptoStats_t,
+    e: RTypes_CryptoAuth2_Session_t,
 }

+ 1 - 0
util/events/libuv/Pipe.c

@@ -215,6 +215,7 @@ static void incoming(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
         m->padding = Pipe_PADDING_AMOUNT;
         m->capacity = buf->len;
         m->bytes = (uint8_t*)buf->base;
+        m->ad = &m->bytes[-Pipe_PADDING_AMOUNT];
         m->alloc = alloc;
         if (pipe->ipc) {
             #ifndef win32

+ 1 - 0
util/events/libuv/UDPAddrIface.c

@@ -164,6 +164,7 @@ static void incoming(uv_udp_t* handle,
         m->padding = UDPAddrIface_PADDING_AMOUNT + context->pub.generic.addr->addrLen;
         m->capacity = buf->len;
         m->bytes = (uint8_t*)buf->base;
+        m->ad = &m->bytes[-m->padding];
         m->alloc = alloc;
         Er_assert(Message_epush(m, addr, context->pub.generic.addr->addrLen - Sockaddr_OVERHEAD));
 

+ 5 - 5
wire/Message.c

@@ -55,17 +55,17 @@ int Message_getAssociatedFd(struct Message* msg)
 struct Message* Message_clone(struct Message* toClone, struct Allocator* alloc)
 {
     Assert_true(toClone->capacity >= toClone->length);
-    int32_t len = toClone->capacity + toClone->padding;
+    int32_t len = toClone->capacity + toClone->padding + toClone->adLen;
     uint8_t* allocation = Allocator_malloc(alloc, len + 8);
-    while (((uintptr_t)allocation % 8) != (((uintptr_t)toClone->bytes - toClone->padding) % 8)) {
+    while (((uintptr_t)allocation % 8) != (((uintptr_t)toClone->bytes - toClone->padding - toClone->adLen) % 8)) {
         allocation++;
     }
-    Bits_memcpy(allocation, toClone->bytes - toClone->padding, len);
+    Bits_memcpy(allocation, toClone->bytes - toClone->padding - toClone->adLen, len);
     return Allocator_clone(alloc, (&(struct Message) {
         .length = toClone->length,
         .padding = toClone->padding,
-        .bytes = allocation + toClone->padding,
-        .ad = allocation,
+        .bytes = allocation + toClone->adLen + toClone->padding,
+        .ad = allocation + toClone->adLen,
         .adLen = toClone->adLen,
         .capacity = toClone->capacity,
         .alloc = alloc