Browse Source

re-shuffled tests to be able to run on both new and old CryptoAuth

Caleb James DeLisle 3 years ago
parent
commit
6d9ecb7e55

+ 2 - 44
Cargo.lock

@@ -73,9 +73,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cbindgen"
-version = "0.15.0"
+version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1df6a11bba1d7cab86c166cecf4cf8acd7d02b7b65924d81b33d27197f22ee35"
+checksum = "9344318b9c787667b95cd2c5124f5eaf2bde35e959dd01ea04fc5b234c542c11"
 dependencies = [
  "clap",
  "heck",
@@ -297,26 +297,12 @@ dependencies = [
  "cfg-if 0.1.10",
 ]
 
-[[package]]
-name = "makekeys"
-version = "0.1.0"
-dependencies = [
- "cjdns_sys",
-]
-
 [[package]]
 name = "memchr"
 version = "2.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
 
-[[package]]
-name = "mkpasswd"
-version = "0.1.0"
-dependencies = [
- "cjdns_sys",
-]
-
 [[package]]
 name = "nom"
 version = "5.1.2"
@@ -345,13 +331,6 @@ version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
 
-[[package]]
-name = "privatetopublic"
-version = "0.1.0"
-dependencies = [
- "cjdns_sys",
-]
-
 [[package]]
 name = "proc-macro2"
 version = "1.0.24"
@@ -361,13 +340,6 @@ dependencies = [
  "unicode-xid",
 ]
 
-[[package]]
-name = "publictoip6"
-version = "0.1.0"
-dependencies = [
- "cjdns_sys",
-]
-
 [[package]]
 name = "quick-error"
 version = "1.2.3"
@@ -424,13 +396,6 @@ dependencies = [
  "rand_core",
 ]
 
-[[package]]
-name = "randombytes"
-version = "0.1.0"
-dependencies = [
- "cjdns_sys",
-]
-
 [[package]]
 name = "redox_syscall"
 version = "0.1.57"
@@ -537,13 +502,6 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
-[[package]]
-name = "sybilsim"
-version = "0.1.0"
-dependencies = [
- "cjdns_sys",
-]
-
 [[package]]
 name = "syn"
 version = "1.0.52"

+ 0 - 6
Cargo.toml

@@ -3,13 +3,7 @@
 members = [
     "rust/cjdns_sys",
     "rust/cjdroute",
-    "rust/publictoip6",
-    "rust/mkpasswd",
-    "rust/sybilsim",
     "rust/testcjdroute",
-    "rust/randombytes",
-    "rust/privatetopublic",
-    "rust/makekeys",
 ]
 
 [profile.release]

+ 4 - 4
admin/AuthorizedPasswords.c

@@ -86,13 +86,13 @@ static void list(Dict* args, void* vcontext, String* txid, struct Allocator* req
     int64_t* page_p = Dict_getIntC(args, "page");
     int page = (page_p) ? *page_p : 0;
 
-    struct StringList* users = CryptoAuth_getUsers(context->ca, requestAlloc);
+    RTypes_StrList_t* users = CryptoAuth_getUsers(context->ca, requestAlloc);
     List* out = List_new(requestAlloc);
-    for (int i = page * 16; i < users->length && i < (page + 1) * 16; i++) {
-        List_addString(out, StringList_get(users, i), requestAlloc);
+    for (int i = page * 16; i < users->len && i < (page + 1) * 16; i++) {
+        List_addString(out, users->items[i], requestAlloc);
     }
     Dict* response = Dict_new(requestAlloc);
-    Dict_putIntC(response, "total", users->length, requestAlloc);
+    Dict_putIntC(response, "total", users->len, requestAlloc);
     Dict_putListC(response, "users", out, requestAlloc);
     Admin_sendMessage(response, txid, context->admin);
 }

+ 1 - 1
admin/angel/Core.c

@@ -241,7 +241,7 @@ static void initTunfd(Dict* args, void* vcontext, String* txid, struct Allocator
     }
     struct Iface* iface = NULL;
     if (type == TUNMessageType_NONE) {
-        Rffi_IfWrapper_t aw = Rffi_android_create(tunAlloc);
+        RTypes_IfWrapper_t aw = Rffi_android_create(tunAlloc);
         Iface_plumb(aw.external, &p->iface);
         iface = aw.internal;
     } else {

+ 83 - 31
crypto/CryptoAuth.c

@@ -277,14 +277,14 @@ static inline void encrypt(uint32_t nonce,
 
 static inline bool knowHerKey(struct CryptoAuth_Session_pvt* session)
 {
-    return !Bits_isZero(session->pub.herPublicKey, 32);
+    return !Bits_isZero(session->herPublicKey, 32);
 }
 
 static void getIp6(struct CryptoAuth_Session_pvt* session, uint8_t* addr)
 {
     Assert_true(knowHerKey(session));
     uint8_t ip6[16];
-    AddressCalc_addressForPublicKey(ip6, session->pub.herPublicKey);
+    AddressCalc_addressForPublicKey(ip6, session->herPublicKey);
     AddrTools_printIp(addr, ip6);
 }
 
@@ -293,7 +293,7 @@ static void getIp6(struct CryptoAuth_Session_pvt* session, uint8_t* addr)
         if (!Defined(Log_DEBUG)) { break; }                                                      \
         uint8_t addr[40] = "unknown";                                                            \
         getIp6((session), addr);                                                                 \
-        String* dn = (session)->pub.displayName;                                                 \
+        String* dn = (session)->displayName;                                                     \
         Log_debug((session)->context->logger, "%p %s [%s] state[%d]: " format, (void*)(session), \
                   dn ? dn->bytes : "", addr, (session)->nextNonce, __VA_ARGS__);                 \
     } while (0)
@@ -313,7 +313,7 @@ static void reset(struct CryptoAuth_Session_pvt* session)
     Bits_memset(session->sharedSecret, 0, 32);
     session->established = false;
 
-    Bits_memset(&session->pub.replayProtector, 0, sizeof(struct ReplayProtector));
+    Bits_memset(&session->replayProtector, 0, sizeof(struct ReplayProtector));
 }
 
 static void resetIfTimeout(struct CryptoAuth_Session_pvt* session)
@@ -326,9 +326,9 @@ static void resetIfTimeout(struct CryptoAuth_Session_pvt* session)
     }
 
     uint64_t nowSecs = Time_currentTimeSeconds(session->context->eventBase);
-    if (nowSecs - session->timeOfLastPacket < session->pub.setupResetAfterInactivitySeconds) {
+    if (nowSecs - session->timeOfLastPacket < session->setupResetAfterInactivitySeconds) {
         return;
-    } else if (nowSecs - session->timeOfLastPacket < session->pub.resetAfterInactivitySeconds) {
+    } else if (nowSecs - session->timeOfLastPacket < session->resetAfterInactivitySeconds) {
         if (session->established) { return; }
     }
 
@@ -352,7 +352,7 @@ static void encryptHandshake(struct Message* message,
                  CryptoHeader_Challenge_SIZE + 24);
 
     // set the permanent key
-    Bits_memcpy(header->publicKey, session->context->pub.publicKey, 32);
+    Bits_memcpy(header->publicKey, session->context->pubKey, 32);
 
     Assert_true(knowHerKey(session));
 
@@ -414,7 +414,7 @@ static void encryptHandshake(struct Message* message,
     if (session->nextNonce < CryptoAuth_State_RECEIVED_HELLO) {
         getSharedSecret(sharedSecret,
                         session->context->privateKey,
-                        session->pub.herPublicKey,
+                        session->herPublicKey,
                         passwordHash,
                         session->context->logger);
 
@@ -540,7 +540,7 @@ static inline enum CryptoAuth_DecryptErr decryptMessage(struct CryptoAuth_Sessio
         cryptoAuthDebug0(session, "DROP authenticated decryption failed");
         return CryptoAuth_DecryptErr_DECRYPT;
     }
-    if (!ReplayProtector_checkNonce(nonce, &session->pub.replayProtector)) {
+    if (!ReplayProtector_checkNonce(nonce, &session->replayProtector)) {
         cryptoAuthDebug(session, "DROP nonce checking failed nonce=[%u]", nonce);
         return CryptoAuth_DecryptErr_REPLAY;
     }
@@ -572,7 +572,7 @@ static enum CryptoAuth_DecryptErr decryptHandshake(struct CryptoAuth_Session_pvt
     // nextNonce >3: handshake complete
 
     Assert_true(knowHerKey(session));
-    if (Bits_memcmp(session->pub.herPublicKey, header->publicKey, 32)) {
+    if (Bits_memcmp(session->herPublicKey, header->publicKey, 32)) {
         cryptoAuthDebug0(session, "DROP a packet with different public key than this session");
         return CryptoAuth_DecryptErr_WRONG_PERM_PUBKEY;
     }
@@ -587,7 +587,7 @@ static enum CryptoAuth_DecryptErr decryptHandshake(struct CryptoAuth_Session_pvt
         passwordHash = userObj->secret;
         if (userObj->restrictedToip6[0]) {
             restrictedToip6 = userObj->restrictedToip6;
-            if (!ip6MatchesKey(restrictedToip6, session->pub.herPublicKey)) {
+            if (!ip6MatchesKey(restrictedToip6, session->herPublicKey)) {
                 cryptoAuthDebug0(session, "DROP packet with key not matching restrictedToip6");
                 return CryptoAuth_DecryptErr_IP_RESTRICTED;
             }
@@ -614,7 +614,7 @@ static enum CryptoAuth_DecryptErr decryptHandshake(struct CryptoAuth_Session_pvt
 
         getSharedSecret(sharedSecret,
                         session->context->privateKey,
-                        session->pub.herPublicKey,
+                        session->herPublicKey,
                         passwordHash,
                         session->context->logger);
         nextNonce = CryptoAuth_State_RECEIVED_HELLO;
@@ -632,7 +632,7 @@ static enum CryptoAuth_DecryptErr decryptHandshake(struct CryptoAuth_Session_pvt
         // We sent the hello, this is a key
         getSharedSecret(sharedSecret,
                         session->ourTempPrivKey,
-                        session->pub.herPublicKey,
+                        session->herPublicKey,
                         passwordHash,
                         session->context->logger);
         nextNonce = CryptoAuth_State_RECEIVED_KEY;
@@ -762,8 +762,8 @@ static enum CryptoAuth_DecryptErr decryptHandshake(struct CryptoAuth_Session_pvt
             // fresh new hello packet, we should reset the session.
             switch (session->nextNonce) {
                 case CryptoAuth_State_SENT_HELLO: {
-                    if (Bits_memcmp(session->pub.herPublicKey,
-                                    session->context->pub.publicKey, 32) < 0)
+                    if (Bits_memcmp(session->herPublicKey,
+                                    session->context->pubKey, 32) < 0)
                     {
                         // It's a hello and we are the initiator but their permant public key is
                         // numerically lower than ours, this is so that in the event of two hello
@@ -824,7 +824,7 @@ static enum CryptoAuth_DecryptErr decryptHandshake(struct CryptoAuth_Session_pvt
     );
     session->nextNonce = nextNonce;
 
-    Bits_memset(&session->pub.replayProtector, 0, sizeof(struct ReplayProtector));
+    Bits_memset(&session->replayProtector, 0, sizeof(struct ReplayProtector));
 
     return 0;
 }
@@ -869,8 +869,8 @@ enum CryptoAuth_DecryptErr CryptoAuth_decrypt(struct CryptoAuth_Session* session
             enum CryptoAuth_DecryptErr ret = decryptMessage(session, nonce, msg, secret);
 
             // This prevents a few "ghost" dropped packets at the beginning of a session.
-            session->pub.replayProtector.baseOffset = nonce + 1;
-            session->pub.replayProtector.bitfield = 0;
+            session->replayProtector.baseOffset = nonce + 1;
+            session->replayProtector.bitfield = 0;
 
             if (!ret) {
                 cryptoAuthDebug0(session, "Final handshake step succeeded");
@@ -931,11 +931,11 @@ struct CryptoAuth* CryptoAuth_new(struct Allocator* allocator,
     } else {
         Random_bytes(rand, ca->privateKey, 32);
     }
-    crypto_scalarmult_curve25519_base(ca->pub.publicKey, ca->privateKey);
+    crypto_scalarmult_curve25519_base(ca->pubKey, ca->privateKey);
 
     if (Defined(Log_KEYS)) {
         uint8_t publicKeyHex[65];
-        printHexKey(publicKeyHex, ca->pub.publicKey);
+        printHexKey(publicKeyHex, ca->pubKey);
         uint8_t privateKeyHex[65];
         printHexKey(privateKeyHex, ca->privateKey);
         Log_keys(logger,
@@ -1023,16 +1023,25 @@ int CryptoAuth_removeUsers(struct CryptoAuth* context, String* login)
     return count;
 }
 
-struct StringList* CryptoAuth_getUsers(struct CryptoAuth* context, struct Allocator* alloc)
+RTypes_StrList_t* CryptoAuth_getUsers(const struct CryptoAuth* context, struct Allocator* alloc)
 {
     struct CryptoAuth_pvt* ca = Identity_check((struct CryptoAuth_pvt*) context);
 
-    struct StringList* users = StringList_new(alloc);
+    int count = 0;
+    for (struct CryptoAuth_User* u = ca->users; u; u = u->next) {
+        count++;
+    }
+
+    RTypes_StrList_t* out = Allocator_calloc(alloc, sizeof(RTypes_StrList_t), 1);
+    out->len = count;
+    out->items = Allocator_calloc(alloc, sizeof(String*), count);
+    int i = 0;
     for (struct CryptoAuth_User* u = ca->users; u; u = u->next) {
-        StringList_add(users, String_clone(u->login, alloc));
+        out->items[i] = String_clone(u->login, alloc);
+        i++;
     }
 
-    return users;
+    return out;
 }
 
 struct CryptoAuth_Session* CryptoAuth_newSession(struct CryptoAuth* ca,
@@ -1047,19 +1056,19 @@ struct CryptoAuth_Session* CryptoAuth_newSession(struct CryptoAuth* ca,
     Identity_set(session);
     session->context = context;
     session->requireAuth = requireAuth;
-    session->pub.displayName = displayName ? String_new(displayName, alloc) : NULL;
+    session->displayName = displayName ? String_new(displayName, alloc) : NULL;
     session->timeOfLastPacket = Time_currentTimeSeconds(context->eventBase);
     session->alloc = alloc;
 
-    session->pub.resetAfterInactivitySeconds = CryptoAuth_DEFAULT_RESET_AFTER_INACTIVITY_SECONDS;
-    session->pub.setupResetAfterInactivitySeconds =
+    session->resetAfterInactivitySeconds = CryptoAuth_DEFAULT_RESET_AFTER_INACTIVITY_SECONDS;
+    session->setupResetAfterInactivitySeconds =
         CryptoAuth_DEFAULT_SETUP_RESET_AFTER_INACTIVITY_SECONDS;
 
     Assert_true(herPublicKey);
-    Bits_memcpy(session->pub.herPublicKey, herPublicKey, 32);
+    Bits_memcpy(session->herPublicKey, herPublicKey, 32);
     uint8_t calculatedIp6[16];
     AddressCalc_addressForPublicKey(calculatedIp6, herPublicKey);
-    Bits_memcpy(session->pub.herIp6, calculatedIp6, 16);
+    Bits_memcpy(session->herIp6, calculatedIp6, 16);
 
     return &session->pub;
 }
@@ -1099,13 +1108,13 @@ void CryptoAuth_setAuth(const String* password,
     reset(session);
 }
 
-enum CryptoAuth_State CryptoAuth_getState(struct CryptoAuth_Session* caSession)
+RTypes_CryptoAuth_State_t CryptoAuth_getState(struct CryptoAuth_Session* caSession)
 {
     struct CryptoAuth_Session_pvt* session =
         Identity_check((struct CryptoAuth_Session_pvt*)caSession);
 
     if (session->nextNonce <= CryptoAuth_State_RECEIVED_KEY) {
-        return session->nextNonce;
+        return (RTypes_CryptoAuth_State_t) session->nextNonce;
     }
     return (session->established) ? CryptoAuth_State_ESTABLISHED : CryptoAuth_State_RECEIVED_KEY;
 }
@@ -1124,6 +1133,48 @@ void CryptoAuth_reset(struct CryptoAuth_Session* caSession)
     reset(session);
 }
 
+void CryptoAuth_getHerPubKey(const struct CryptoAuth_Session* session, uint8_t* pkOut)
+{
+    const struct CryptoAuth_Session_pvt* s =
+        Identity_check((struct CryptoAuth_Session_pvt*)session);
+    Bits_memcpy(pkOut, s->herPublicKey, 32);
+}
+
+void CryptoAuth_getHerIp6(const struct CryptoAuth_Session* session, uint8_t* ipOut)
+{
+    const struct CryptoAuth_Session_pvt* s =
+        Identity_check((struct CryptoAuth_Session_pvt*)session);
+    Bits_memcpy(ipOut, s->herIp6, 16);
+}
+
+void CryptoAuth_getPubKey(const struct CryptoAuth* ca, uint8_t* pkOut)
+{
+    const struct CryptoAuth_pvt* context = Identity_check((struct CryptoAuth_pvt*) ca);
+    Bits_memcpy(pkOut,  context->pubKey, 32);
+}
+
+String_t *CryptoAuth_getName(const struct CryptoAuth_Session* session, Allocator_t* alloc)
+{
+    const struct CryptoAuth_Session_pvt* s =
+        Identity_check((struct CryptoAuth_Session_pvt*)session);
+    if (s->displayName) {
+        return String_clone(s->displayName, alloc);
+    } else {
+        return NULL;
+    }
+}
+
+void CryptoAuth_stats(const struct CryptoAuth_Session* session, RTypes_CryptoStats_t* statsOut)
+{
+    const struct CryptoAuth_Session_pvt* s =
+        Identity_check((struct CryptoAuth_Session_pvt*)session);
+    statsOut->received_packets = s->replayProtector.baseOffset +
+        Bits_popCountx64(s->replayProtector.bitfield);
+    statsOut->lost_packets = s->replayProtector.lostPackets;
+    statsOut->received_unexpected = s->replayProtector.receivedOutOfRange;
+    statsOut->duplicate_packets = s->replayProtector.duplicates;
+}
+
 // For testing:
 void CryptoAuth_encryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32])
 {
@@ -1134,3 +1185,4 @@ int CryptoAuth_decryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t s
 {
     return decryptRndNonce(nonce, msg, secret);
 }
+

+ 23 - 45
crypto/CryptoAuth.h

@@ -15,7 +15,8 @@
 #ifndef CryptoAuth_H
 #define CryptoAuth_H
 
-#include "benc/StringList.h"
+#include "rust/cjdns_sys/RTypes.h"
+#include "benc/String.h"
 #include "crypto/random/Random.h"
 #include "crypto/ReplayProtector.h"
 #include "memory/Allocator.h"
@@ -34,31 +35,12 @@ Linker_require("crypto/CryptoAuth.c")
 
 struct CryptoAuth
 {
-    uint8_t publicKey[32];
+    int opaque;
 };
 
 struct CryptoAuth_Session
 {
-    uint8_t herPublicKey[32];
-
-    String* displayName;
-
-    struct ReplayProtector replayProtector;
-
-    /**
-     * Bind this CryptoAuth session to the other node's ip6 address,
-     * any packet avertizing a key which doesn't hash to this will be dropped.
-     */
-    uint8_t herIp6[16];
-
-    /**
-     * After this number of seconds of inactivity,
-     * a connection will be reset to prevent them hanging in a bad state.
-     */
-    uint32_t resetAfterInactivitySeconds;
-
-    /** If a session is not completely setup, reset it after this many seconds of inactivity. */
-    uint32_t setupResetAfterInactivitySeconds;
+    int opaque;
 };
 
 /**
@@ -108,7 +90,7 @@ int CryptoAuth_removeUsers(struct CryptoAuth* context, String* user);
  * @param alloc the Allocator to use to create the usersOut array.
  * @returns List* containing the user String's
  */
-struct StringList* CryptoAuth_getUsers(struct CryptoAuth* context, struct Allocator* alloc);
+RTypes_StrList_t* CryptoAuth_getUsers(const struct CryptoAuth* context, struct Allocator* alloc);
 
 /**
  * Create a new crypto authenticator.
@@ -223,28 +205,14 @@ void CryptoAuth_resetIfTimeout(struct CryptoAuth_Session* session);
 
 void CryptoAuth_reset(struct CryptoAuth_Session* caSession);
 
-enum CryptoAuth_State {
-    // New CryptoAuth session, has not sent or received anything
-    CryptoAuth_State_INIT = 0,
-
-    // Sent a hello message, waiting for reply
-    CryptoAuth_State_SENT_HELLO = 1,
-
-    // Received a hello message, have not yet sent a reply
-    CryptoAuth_State_RECEIVED_HELLO = 2,
-
-    // Received a hello message, sent a key message, waiting for the session to complete
-    CryptoAuth_State_SENT_KEY = 3,
+#define CryptoAuth_State_INIT           RTypes_CryptoAuth_State_t_Init
+#define CryptoAuth_State_SENT_HELLO     RTypes_CryptoAuth_State_t_SentHello
+#define CryptoAuth_State_RECEIVED_HELLO RTypes_CryptoAuth_State_t_ReceivedHello
+#define CryptoAuth_State_SENT_KEY       RTypes_CryptoAuth_State_t_SentKey
+#define CryptoAuth_State_RECEIVED_KEY   RTypes_CryptoAuth_State_t_ReceivedKey
+#define CryptoAuth_State_ESTABLISHED    RTypes_CryptoAuth_State_t_Established
 
-    // Sent a hello message, received a key message, may or may not have sent some data traffic
-    // but no data traffic has yet been received
-    CryptoAuth_State_RECEIVED_KEY = 4,
-
-    // Received data traffic, session is in run state
-    CryptoAuth_State_ESTABLISHED = 100
-};
-
-static inline char* CryptoAuth_stateString(int state)
+static inline char* CryptoAuth_stateString(RTypes_CryptoAuth_State_t state)
 {
     switch (state) {
         case CryptoAuth_State_INIT:           return "INIT";
@@ -257,6 +225,16 @@ static inline char* CryptoAuth_stateString(int state)
     }
 }
 
-enum CryptoAuth_State CryptoAuth_getState(struct CryptoAuth_Session* session);
+RTypes_CryptoAuth_State_t CryptoAuth_getState(struct CryptoAuth_Session* session);
+
+void CryptoAuth_getHerPubKey(const struct CryptoAuth_Session *session, uint8_t *pkOut);
+
+void CryptoAuth_getHerIp6(const struct CryptoAuth_Session *session, uint8_t *ipOut);
+
+void CryptoAuth_getPubKey(const struct CryptoAuth *ca, uint8_t *pkOut);
+
+String_t *CryptoAuth_getName(const struct CryptoAuth_Session *session, Allocator_t *alloc);
+
+void CryptoAuth_stats(const struct CryptoAuth_Session *session, RTypes_CryptoStats_t *statsOut);
 
 #endif

+ 23 - 0
crypto/CryptoAuth_pvt.h

@@ -51,6 +51,8 @@ struct CryptoAuth_pvt
 {
     struct CryptoAuth pub;
 
+    uint8_t pubKey[32];
+
     uint8_t privateKey[32];
 
     struct CryptoAuth_User* users;
@@ -69,6 +71,27 @@ struct CryptoAuth_Session_pvt
 {
     struct CryptoAuth_Session pub;
 
+    uint8_t herPublicKey[32];
+
+    String* displayName;
+
+    struct ReplayProtector replayProtector;
+
+    /**
+     * Bind this CryptoAuth session to the other node's ip6 address,
+     * any packet avertizing a key which doesn't hash to this will be dropped.
+     */
+    uint8_t herIp6[16];
+
+    /**
+     * After this number of seconds of inactivity,
+     * a connection will be reset to prevent them hanging in a bad state.
+     */
+    uint32_t resetAfterInactivitySeconds;
+
+    /** If a session is not completely setup, reset it after this many seconds of inactivity. */
+    uint32_t setupResetAfterInactivitySeconds;
+
     struct Allocator* alloc;
 
     /** The shared secret. */

+ 27 - 24
crypto/test/CryptoAuth_fuzz_test.c → crypto/test/CryptoAuthFuzz.c

@@ -12,8 +12,9 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
+#include "crypto/test/CryptoAuthFuzz.h"
 #include "crypto/random/Random.h"
-#include "crypto/CryptoAuth.h"
+#include "crypto/test/TestCa.h"
 #include "benc/String.h"
 #include "memory/MallocAllocator.h"
 #include "util/events/EventBase.h"
@@ -25,7 +26,6 @@
 #include "crypto/random/test/DeterminentRandomSeed.h"
 #include "crypto/random/Random.h"
 #include "crypto/AddressCalc.h"
-#include "test/FuzzTest.h"
 
 struct DelayedMsg {
     struct Message* msg;
@@ -36,10 +36,11 @@ struct DelayedMsg {
 };
 
 struct Node {
-    struct CryptoAuth* ca;
-    struct CryptoAuth_Session* session;
+    TestCa_t* ca;
+    TestCa_Session_t* session;
     struct DelayedMsg* delayedMsgs;
     int sendCounter;
+    uint8_t pubKey[32];
 };
 
 struct Context {
@@ -78,7 +79,7 @@ static bool maybe(struct Context* ctx, uint32_t chanceIsOneInWhat)
 static void resetNode(struct Context* ctx, struct Node* node)
 {
     logNode0(ctx, node, "RESET");
-    CryptoAuth_reset(node->session);
+    TestCa_reset(node->session);
 }
 
 /**
@@ -209,7 +210,7 @@ static void sendFrom(struct Context* ctx, struct Node* from, struct Message* msg
         flippedImmutable = true;
     }
 
-    if (!CryptoAuth_decrypt(to->session, msg)) {
+    if (!TestCa_decrypt(to->session, msg)) {
         Assert_true(!flippedImmutable);
         Assert_true(msg->length == 4 && !Bits_memcmp(msg->bytes, "hey", 4));
         if (to == &ctx->nodeB) {
@@ -217,11 +218,11 @@ static void sendFrom(struct Context* ctx, struct Node* from, struct Message* msg
             if (maybe(ctx, 10)) {
                 return;
             }
-            Assert_true(!CryptoAuth_encrypt(to->session, msg));
+            Assert_true(!TestCa_encrypt(to->session, msg));
             to->sendCounter++;
             sendFrom(ctx, to, msg);
-        } else if (CryptoAuth_getState(ctx->nodeA.session) == CryptoAuth_State_ESTABLISHED &&
-            CryptoAuth_getState(ctx->nodeB.session) == CryptoAuth_State_ESTABLISHED)
+        } else if (TestCa_getState(ctx->nodeA.session) == RTypes_CryptoAuth_State_t_Established &&
+            TestCa_getState(ctx->nodeB.session) == RTypes_CryptoAuth_State_t_Established)
         {
             ctx->successMessageCount++;
         }
@@ -259,7 +260,7 @@ static void mainLoop(struct Context* ctx)
         struct Allocator* alloc = Allocator_child(ctx->alloc);
         struct Message* msg = Message_new(0, 512, alloc);
         Er_assert(Message_epush(msg, "hey", 4));
-        Assert_true(!CryptoAuth_encrypt(ctx->nodeA.session, msg));
+        Assert_true(!TestCa_encrypt(ctx->nodeA.session, msg));
         sendFrom(ctx, &ctx->nodeA, msg);
         Allocator_free(alloc);
     }
@@ -267,22 +268,24 @@ static void mainLoop(struct Context* ctx)
     Assert_failure("Nodes could not sync");
 }
 
-void* CJDNS_FUZZ_INIT(struct Allocator* alloc, struct Random* rand)
+void* CryptoAuthFuzz_init(struct Allocator* alloc, struct Random* rand, enum TestCa_Config cfg)
 {
     struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1);
     Identity_set(ctx);
     struct EventBase* base = EventBase_new(alloc);
     ctx->alloc = alloc;
-    ctx->nodeA.ca = CryptoAuth_new(alloc, NULL, base, NULL, rand);
-    ctx->nodeB.ca = CryptoAuth_new(alloc, NULL, base, NULL, rand);
-    ctx->nodeA.session = CryptoAuth_newSession(
-        ctx->nodeA.ca, alloc, ctx->nodeB.ca->publicKey, false, "nodeA");
-    ctx->nodeB.session = CryptoAuth_newSession(
-        ctx->nodeB.ca, alloc, ctx->nodeA.ca->publicKey, false, "nodeB");
+    ctx->nodeA.ca = TestCa_new(alloc, NULL, base, NULL, rand, cfg);
+    ctx->nodeB.ca = TestCa_new(alloc, NULL, base, NULL, rand, cfg);
+    TestCa_getPubKey(ctx->nodeA.ca, ctx->nodeA.pubKey);
+    TestCa_getPubKey(ctx->nodeB.ca, ctx->nodeB.pubKey);
+    ctx->nodeA.session = TestCa_newSession(
+        ctx->nodeA.ca, alloc, ctx->nodeB.pubKey, false, "nodeA", true);
+    ctx->nodeB.session = TestCa_newSession(
+        ctx->nodeB.ca, alloc, ctx->nodeA.pubKey, false, "nodeB", true);
     return ctx;
 }
 
-void CJDNS_FUZZ_MAIN(void* vctx, struct Message* fuzz)
+void CryptoAuthFuzz_main(void* vctx, struct Message* fuzz)
 {
     struct Context* ctx = Identity_check((struct Context*) vctx);
 
@@ -291,24 +294,24 @@ void CJDNS_FUZZ_MAIN(void* vctx, struct Message* fuzz)
     ctx->rand = Random_newWithSeed(ctx->alloc, NULL, rs, NULL);
 
     if (maybe(ctx, 2)) {
-        CryptoAuth_addUser_ipv6(String_CONST("pass"), String_CONST("user"), NULL, ctx->nodeB.ca);
+        TestCa_addUser_ipv6(String_CONST("pass"), String_CONST("user"), NULL, ctx->nodeB.ca);
     } else {
         uint8_t nodeAAddress[16];
-        AddressCalc_addressForPublicKey(nodeAAddress, ctx->nodeA.ca->publicKey);
-        CryptoAuth_addUser_ipv6(String_CONST("pass"),
+        AddressCalc_addressForPublicKey(nodeAAddress, ctx->nodeA.pubKey);
+        TestCa_addUser_ipv6(String_CONST("pass"),
                                 String_CONST("user"),
                                 nodeAAddress,
                                 ctx->nodeB.ca);
     }
     if (maybe(ctx, 3)) {
         // 33% chance of no authentication
-        CryptoAuth_removeUsers(ctx->nodeB.ca, String_CONST("user"));
+        TestCa_removeUsers(ctx->nodeB.ca, String_CONST("user"));
     } else if (maybe(ctx, 2)) {
         // 33% chance of authType 2
-        CryptoAuth_setAuth(String_CONST("pass"), String_CONST("user"), ctx->nodeA.session);
+        TestCa_setAuth(String_CONST("pass"), String_CONST("user"), ctx->nodeA.session);
     } else {
         // 33% chance of authType 1
-        CryptoAuth_setAuth(String_CONST("pass"), NULL, ctx->nodeA.session);
+        TestCa_setAuth(String_CONST("pass"), NULL, ctx->nodeA.session);
     }
 
     mainLoop(ctx);

+ 28 - 0
crypto/test/CryptoAuthFuzz.h

@@ -0,0 +1,28 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef CRYPTOAUTHFUZZ_H
+#define CRYPTOAUTHFUZZ_H
+
+#include "crypto/random/Random.h"
+#include "crypto/test/TestCa.h"
+#include "memory/Allocator.h"
+#include "wire/Message.h"
+#include "util/Linker.h"
+Linker_require("crypto/test/CryptoAuthFuzz.c")
+
+void* CryptoAuthFuzz_init(struct Allocator* alloc, struct Random* rand, enum TestCa_Config cfg);
+void CryptoAuthFuzz_main(void* vctx, struct Message* fuzz);
+
+#endif

+ 27 - 0
crypto/test/CryptoAuthFuzz_noise_fuzz_test.c

@@ -0,0 +1,27 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#include "crypto/test/TestCa.h"
+#include "crypto/test/CryptoAuthFuzz.h"
+#include "test/FuzzTest.h"
+
+void* CJDNS_FUZZ_INIT(struct Allocator* alloc, struct Random* rand)
+{
+    return NULL;
+    //return CryptoAuthFuzz_init(alloc, rand, TestCa_Config_NOISE);
+}
+void CJDNS_FUZZ_MAIN(void* vctx, struct Message* fuzz)
+{
+    //CryptoAuthFuzz_main(vctx, fuzz);
+}

+ 0 - 0
crypto/test/CryptoAuth_fuzz_test_cases/Default.hex → crypto/test/CryptoAuthFuzz_noise_fuzz_test_cases/Default.hex


+ 26 - 0
crypto/test/CryptoAuthFuzz_old_fuzz_test.c

@@ -0,0 +1,26 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#include "crypto/test/TestCa.h"
+#include "crypto/test/CryptoAuthFuzz.h"
+#include "test/FuzzTest.h"
+
+void* CJDNS_FUZZ_INIT(struct Allocator* alloc, struct Random* rand)
+{
+    return CryptoAuthFuzz_init(alloc, rand, TestCa_Config_OLD);
+}
+void CJDNS_FUZZ_MAIN(void* vctx, struct Message* fuzz)
+{
+    CryptoAuthFuzz_main(vctx, fuzz);
+}

+ 4 - 0
crypto/test/CryptoAuthFuzz_old_fuzz_test_cases/Default.hex

@@ -0,0 +1,4 @@
+# This test only seeds a DeterminentRandomSeed so we're just
+# specifying the default as all zeros.
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000

+ 27 - 0
crypto/test/CryptoAuthFuzz_oldnew_fuzz_test.c

@@ -0,0 +1,27 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#include "crypto/test/TestCa.h"
+#include "crypto/test/CryptoAuthFuzz.h"
+#include "test/FuzzTest.h"
+
+void* CJDNS_FUZZ_INIT(struct Allocator* alloc, struct Random* rand)
+{
+    return NULL;
+    //return CryptoAuthFuzz_init(alloc, rand, TestCa_Config_OLD_NEW);
+}
+void CJDNS_FUZZ_MAIN(void* vctx, struct Message* fuzz)
+{
+    //CryptoAuthFuzz_main(vctx, fuzz);
+}

+ 4 - 0
crypto/test/CryptoAuthFuzz_oldnew_fuzz_test_cases/Default.hex

@@ -0,0 +1,4 @@
+# This test only seeds a DeterminentRandomSeed so we're just
+# specifying the default as all zeros.
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000

+ 55 - 0
crypto/test/CryptoAuth_randnonce_test.c

@@ -0,0 +1,55 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#include "crypto/CryptoAuth_pvt.h"
+#include "util/Hex.h"
+#include "util/Bits.h"
+
+#include <stdio.h>
+
+#define HELLOWORLDLOWER "hello world"
+#define HELLOWORLDLEN 12
+
+static void encryptRndNonceTest()
+{
+    uint8_t buff[44];
+    Bits_memset(buff, 0, 44);
+
+    uint8_t nonce[24];
+    Bits_memset(nonce, 0, 24);
+
+    uint8_t secret[32];
+    Bits_memset(secret, 0, 32);
+
+    struct Message m = { .bytes=&buff[32], .length=HELLOWORLDLEN, .padding=32};
+    CString_strcpy((char*) m.bytes, HELLOWORLDLOWER);
+
+    CryptoAuth_encryptRndNonce(nonce, &m, secret);
+
+    uint8_t* expected = (uint8_t*) "1391ac5d03ba9f7099bffbb6e6c69d67ae5bd79391a5b94399b293dc";
+    uint8_t output[57];
+    Hex_encode(output, 57, m.bytes, m.length);
+
+    printf("\n%s\n%s\n", (char*) expected, (char*) output);
+    Assert_true(!Bits_memcmp(expected, output, 56));
+
+    Assert_true(!CryptoAuth_decryptRndNonce(nonce, &m, secret));
+    Assert_true(m.length == HELLOWORLDLEN && !Bits_memcmp(m.bytes, HELLOWORLDLOWER, m.length));
+}
+
+int main()
+{
+    encryptRndNonceTest();
+    return 0;
+}

+ 70 - 56
crypto/test/CryptoAuth_test.c

@@ -23,6 +23,7 @@
 #include "util/Endian.h"
 #include "util/log/FileWriterLog.h"
 #include "wire/CryptoHeader.h"
+#include "crypto/test/TestCa.h"
 
 #define PRIVATEKEY_A \
     Constant_stringForHex("53ff22b2eb94ce8c5f1852c0f557eb901f067e5273d541e0a21e143c20dff9da")
@@ -38,11 +39,11 @@
 
 struct Context
 {
-    struct CryptoAuth* ca1;
-    struct CryptoAuth_Session* sess1;
+    TestCa_t* ca1;
+    TestCa_Session_t* sess1;
 
-    struct CryptoAuth* ca2;
-    struct CryptoAuth_Session* sess2;
+    TestCa_t* ca2;
+    TestCa_Session_t* sess2;
 
     struct Allocator* alloc;
     struct Log* log;
@@ -54,7 +55,8 @@ static struct Context* init(uint8_t* privateKeyA,
                             uint8_t* publicKeyA,
                             uint8_t* password,
                             uint8_t* privateKeyB,
-                            uint8_t* publicKeyB)
+                            uint8_t* publicKeyB,
+                            enum TestCa_Config cfg)
 {
     struct Allocator* alloc = MallocAllocator_new(1048576);
     struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1);
@@ -63,27 +65,27 @@ static struct Context* init(uint8_t* privateKeyA,
     struct Random* rand = ctx->rand = Random_new(alloc, logger, NULL);
     struct EventBase* base = ctx->base = EventBase_new(alloc);
 
-    ctx->ca1 = CryptoAuth_new(alloc, privateKeyA, base, logger, rand);
-    ctx->sess1 = CryptoAuth_newSession(ctx->ca1, alloc, publicKeyB, false, "cif1");
+    ctx->ca1 = TestCa_new(alloc, privateKeyA, base, logger, rand, cfg);
+    ctx->sess1 = TestCa_newSession(ctx->ca1, alloc, publicKeyB, false, "cif1", true);
 
-    ctx->ca2 = CryptoAuth_new(alloc, privateKeyB, base, logger, rand);
+    ctx->ca2 = TestCa_new(alloc, privateKeyB, base, logger, rand, cfg);
     if (password) {
         String* passStr = String_CONST(password);
-        CryptoAuth_setAuth(passStr, NULL, ctx->sess1);
-        CryptoAuth_addUser(passStr, String_new(USEROBJ, alloc), ctx->ca2);
+        TestCa_setAuth(passStr, NULL, ctx->sess1);
+        TestCa_addUser_ipv6(passStr, String_new(USEROBJ, alloc), NULL, ctx->ca2);
     }
-    ctx->sess2 = CryptoAuth_newSession(ctx->ca2, alloc, publicKeyA, false, "cif2");
+    ctx->sess2 = TestCa_newSession(ctx->ca2, alloc, publicKeyA, false, "cif2", true);
 
     return ctx;
 }
 
-static struct Context* simpleInit()
+static struct Context* simpleInit(enum TestCa_Config cfg)
 {
-    return init(PRIVATEKEY_A, PUBLICKEY_A, NULL, PRIVATEKEY_B, PUBLICKEY_B);
+    return init(PRIVATEKEY_A, PUBLICKEY_A, NULL, PRIVATEKEY_B, PUBLICKEY_B, cfg);
 }
 
 static struct Message* encryptMsg(struct Context* ctx,
-                                  struct CryptoAuth_Session* encryptWith,
+                                  TestCa_Session_t* encryptWith,
                                   const char* x)
 {
     struct Allocator* alloc = Allocator_child(ctx->alloc);
@@ -92,21 +94,21 @@ static struct Message* encryptMsg(struct Context* ctx,
     CString_strcpy(msg->bytes, x);
     msg->length = CString_strlen(x);
     msg->bytes[msg->length] = 0;
-    Assert_true(!CryptoAuth_encrypt(encryptWith, msg));
+    Assert_true(!TestCa_encrypt(encryptWith, msg));
     Assert_true(msg->length > ((int)CString_strlen(x) + 4));
     return msg;
 }
 
 static void decryptMsg(struct Context* ctx,
                        struct Message* msg,
-                       struct CryptoAuth_Session* decryptWith,
+                       TestCa_Session_t* decryptWith,
                        const char* x)
 {
     if (!x) {
         // x is null implying it is expected to fail.
-        Assert_true(CryptoAuth_decrypt(decryptWith, msg));
+        Assert_true(TestCa_decrypt(decryptWith, msg));
     } else {
-        Assert_true(!CryptoAuth_decrypt(decryptWith, msg));
+        Assert_true(!TestCa_decrypt(decryptWith, msg));
         if ((int)CString_strlen(x) != msg->length ||
             CString_strncmp(msg->bytes, x, msg->length))
         {
@@ -130,9 +132,9 @@ static void sendToIf2(struct Context* ctx, const char* x)
     Allocator_free(msg->alloc);
 }
 
-static void normal()
+static void normal(enum TestCa_Config cfg)
 {
-    struct Context* ctx = simpleInit();
+    struct Context* ctx = simpleInit(cfg);
     sendToIf2(ctx, "hello world");
     sendToIf1(ctx, "hello cjdns");
     sendToIf2(ctx, "hai");
@@ -140,9 +142,9 @@ static void normal()
     Allocator_free(ctx->alloc);
 }
 
-static void repeatKey()
+static void repeatKey(enum TestCa_Config cfg)
 {
-    struct Context* ctx = simpleInit();
+    struct Context* ctx = simpleInit(cfg);
     sendToIf2(ctx, "hello world");
     sendToIf2(ctx, "r u thar?");
     sendToIf1(ctx, "hello cjdns");
@@ -151,9 +153,9 @@ static void repeatKey()
     Allocator_free(ctx->alloc);
 }
 
-static void repeatHello()
+static void repeatHello(enum TestCa_Config cfg)
 {
-    struct Context* ctx = simpleInit();
+    struct Context* ctx = simpleInit(cfg);
     sendToIf2(ctx, "hello world");
     sendToIf2(ctx, "r u thar?");
     sendToIf1(ctx, "hello cjdns");
@@ -162,9 +164,9 @@ static void repeatHello()
     Allocator_free(ctx->alloc);
 }
 
-static void chatter()
+static void chatter(enum TestCa_Config cfg)
 {
-    struct Context* ctx = simpleInit();
+    struct Context* ctx = simpleInit(cfg);
     sendToIf2(ctx, "hello world");
     sendToIf1(ctx, "hello cjdns");
     sendToIf2(ctx, "hai");
@@ -181,9 +183,10 @@ static void chatter()
     Allocator_free(ctx->alloc);
 }
 
-static void auth()
+static void auth(enum TestCa_Config cfg)
 {
-    struct Context* ctx = init(PRIVATEKEY_A, PUBLICKEY_A, "password", PRIVATEKEY_B, PUBLICKEY_B);
+    struct Context* ctx = init(
+        PRIVATEKEY_A, PUBLICKEY_A, "password", PRIVATEKEY_B, PUBLICKEY_B, cfg);
     sendToIf2(ctx, "hello world");
     sendToIf1(ctx, "hello cjdns");
     sendToIf2(ctx, "hai");
@@ -191,9 +194,9 @@ static void auth()
     Allocator_free(ctx->alloc);
 }
 
-static void replayKeyPacket(int scenario)
+static void replayKeyPacket(int scenario, enum TestCa_Config cfg)
 {
-    struct Context* ctx = simpleInit();
+    struct Context* ctx = simpleInit(cfg);
 
     sendToIf2(ctx, "hello world");
 
@@ -227,10 +230,14 @@ static void replayKeyPacket(int scenario)
  * This means two Hello packets crossed on the wire. Both arrived at their destination but
  * if each triggers a re-initialization of the CA session, nobody will be synchronized!
  */
-static void hellosCrossedOnTheWire()
+static void hellosCrossedOnTheWire(enum TestCa_Config cfg)
 {
-    struct Context* ctx = simpleInit();
-    Bits_memcpy(ctx->sess2->herPublicKey, ctx->ca1->publicKey, 32);
+    struct Context* ctx = simpleInit(cfg);
+    uint8_t pk1[32];
+    TestCa_getPubKey(ctx->ca1, pk1);
+    uint8_t hpk2[32];
+    TestCa_getHerPubKey(ctx->sess2, hpk2);
+    Assert_true(!Bits_memcmp(pk1, hpk2, 32));
 
     struct Message* hello2 = encryptMsg(ctx, ctx->sess2, "hello2");
     struct Message* hello1 = encryptMsg(ctx, ctx->sess1, "hello1");
@@ -246,18 +253,18 @@ static void hellosCrossedOnTheWire()
     Allocator_free(ctx->alloc);
 }
 
-static void reset()
+static void reset(enum TestCa_Config cfg)
 {
-    struct Context* ctx = simpleInit();
+    struct Context* ctx = simpleInit(cfg);
     sendToIf2(ctx, "hello world");
     sendToIf1(ctx, "hello cjdns");
     sendToIf2(ctx, "hai");
     sendToIf1(ctx, "brb");
 
-    Assert_true(CryptoAuth_getState(ctx->sess1) == CryptoAuth_State_ESTABLISHED);
-    Assert_true(CryptoAuth_getState(ctx->sess2) == CryptoAuth_State_ESTABLISHED);
+    Assert_true(TestCa_getState(ctx->sess1) == CryptoAuth_State_ESTABLISHED);
+    Assert_true(TestCa_getState(ctx->sess2) == CryptoAuth_State_ESTABLISHED);
 
-    CryptoAuth_reset(ctx->sess1);
+    TestCa_reset(ctx->sess1);
 
     // sess2 still talking to sess1 but sess1 is reset and cannot read the packets.
     decryptMsg(ctx, encryptMsg(ctx, ctx->sess2, "will be lost"), ctx->sess1, NULL);
@@ -271,17 +278,17 @@ static void reset()
     sendToIf1(ctx, "ok works");
     sendToIf2(ctx, "yup");
 
-    Assert_true(CryptoAuth_getState(ctx->sess1) == CryptoAuth_State_ESTABLISHED);
-    Assert_true(CryptoAuth_getState(ctx->sess2) == CryptoAuth_State_ESTABLISHED);
+    Assert_true(TestCa_getState(ctx->sess1) == CryptoAuth_State_ESTABLISHED);
+    Assert_true(TestCa_getState(ctx->sess2) == CryptoAuth_State_ESTABLISHED);
 
     Allocator_free(ctx->alloc);
 }
 
 // This is slightly different from replayKeyPacket because the second key packet is valid,
 // it's just delayed.
-static void twoKeyPackets(int scenario)
+static void twoKeyPackets(int scenario, enum TestCa_Config cfg)
 {
-    struct Context* ctx = simpleInit();
+    struct Context* ctx = simpleInit(cfg);
 
     sendToIf2(ctx, "hello world");
     sendToIf1(ctx, "key packet 1");
@@ -303,20 +310,27 @@ static void twoKeyPackets(int scenario)
     Allocator_free(ctx->alloc);
 }
 
+static void iteration(enum TestCa_Config cfg)
+{
+    normal(cfg);
+    repeatKey(cfg);
+    repeatHello(cfg);
+    chatter(cfg);
+    auth(cfg);
+    replayKeyPacket(1, cfg);
+    replayKeyPacket(2, cfg);
+    replayKeyPacket(3, cfg);
+    hellosCrossedOnTheWire(cfg);
+    reset(cfg);
+    twoKeyPackets(1, cfg);
+    twoKeyPackets(2, cfg);
+    twoKeyPackets(3, cfg);
+}
+
 int main()
 {
-    normal();
-    repeatKey();
-    repeatHello();
-    chatter();
-    auth();
-    replayKeyPacket(1);
-    replayKeyPacket(2);
-    replayKeyPacket(3);
-    hellosCrossedOnTheWire();
-    reset();
-    twoKeyPackets(1);
-    twoKeyPackets(2);
-    twoKeyPackets(3);
+    iteration(TestCa_Config_OLD);
+    //iteration(TestCa_Config_OLD_NEW);
+    //iteration(TestCa_Config_NOISE);
     return 0;
-}
+}

+ 54 - 71
crypto/test/CryptoAuth_unit_test.c

@@ -14,7 +14,6 @@
  */
 #include "benc/List.h"
 #include "benc/String.h"
-#include "crypto/CryptoAuth_pvt.h"
 #include "crypto/random/Random.h"
 #include "crypto/random/test/DeterminentRandomSeed.h"
 #include "io/FileWriter.h"
@@ -27,6 +26,8 @@
 #include "util/log/FileWriterLog.h"
 #include "wire/Error.h"
 #include "wire/Message.h"
+#include "wire/CryptoHeader.h"
+#include "crypto/test/TestCa.h"
 
 #include <stdio.h>
 
@@ -36,33 +37,6 @@
 #define HELLOWORLDLOWER "hello world"
 #define HELLOWORLDLEN 12
 
-static void encryptRndNonceTest()
-{
-    uint8_t buff[44];
-    Bits_memset(buff, 0, 44);
-
-    uint8_t nonce[24];
-    Bits_memset(nonce, 0, 24);
-
-    uint8_t secret[32];
-    Bits_memset(secret, 0, 32);
-
-    struct Message m = { .bytes=&buff[32], .length=HELLOWORLDLEN, .padding=32};
-    CString_strcpy((char*) m.bytes, HELLOWORLDLOWER);
-
-    CryptoAuth_encryptRndNonce(nonce, &m, secret);
-
-    uint8_t* expected = (uint8_t*) "1391ac5d03ba9f7099bffbb6e6c69d67ae5bd79391a5b94399b293dc";
-    uint8_t output[57];
-    Hex_encode(output, 57, m.bytes, m.length);
-
-    printf("\n%s\n%s\n", (char*) expected, (char*) output);
-    Assert_true(!Bits_memcmp(expected, output, 56));
-
-    Assert_true(!CryptoAuth_decryptRndNonce(nonce, &m, secret));
-    Assert_true(m.length == HELLOWORLDLEN && !Bits_memcmp(m.bytes, HELLOWORLDLOWER, m.length));
-}
-
 static struct Random* evilRandom(struct Allocator* alloc, struct Log* logger)
 {
     struct RandomSeed* evilSeed = DeterminentRandomSeed_new(alloc, NULL);
@@ -72,8 +46,8 @@ static struct Random* evilRandom(struct Allocator* alloc, struct Log* logger)
 struct Context
 {
     struct Allocator* alloc;
-    struct CryptoAuth* ca;
-    struct CryptoAuth_Session* sess;
+    TestCa_t* ca;
+    TestCa_Session_t* sess;
     struct Log* log;
     struct EventBase* base;
 };
@@ -81,33 +55,34 @@ struct Context
 static struct Context* setUp(uint8_t* myPrivateKey,
                              uint8_t* herPublicKey,
                              uint8_t* authPassword,
-                             struct Allocator* alloc)
+                             struct Allocator* alloc,
+                             enum TestCa_Config cfg)
 {
     struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1);
     struct Log* log = ctx->log = FileWriterLog_new(stdout, alloc);
     struct EventBase* base = ctx->base = EventBase_new(alloc);
-    struct CryptoAuth* ca = ctx->ca =
-        CryptoAuth_new(alloc, myPrivateKey, base, log, evilRandom(alloc, log));
+    TestCa_t* ca = ctx->ca =
+        TestCa_new(alloc, myPrivateKey, base, log, evilRandom(alloc, log), cfg);
 
-    struct CryptoAuth_Session* sess = ctx->sess =
-        CryptoAuth_newSession(ca, alloc, herPublicKey, false, Gcc_FILE);
+    TestCa_Session_t* sess = ctx->sess =
+        TestCa_newSession(ca, alloc, herPublicKey, false, Gcc_FILE, true);
 
     if (authPassword) {
-        CryptoAuth_setAuth(String_CONST(authPassword), NULL, sess);
+        TestCa_setAuth(String_CONST(authPassword), NULL, sess);
     }
 
     return ctx;
 }
 
-static void testHello(uint8_t* password, uint8_t* expectedOutput)
+static void testHello(uint8_t* password, uint8_t* expectedOutput, enum TestCa_Config cfg)
 {
     Assert_true(CString_strlen((char*)expectedOutput) == 264);
     struct Allocator* alloc = MallocAllocator_new(1<<20);
-    struct Context* ctx = setUp(NULL, HERPUBKEY, password, alloc);
+    struct Context* ctx = setUp(NULL, HERPUBKEY, password, alloc, cfg);
     struct Message* msg = Message_new(0, CryptoHeader_SIZE + 12, alloc);
     Er_assert(Message_epush(msg, HELLOWORLD, HELLOWORLDLEN));
 
-    Assert_true(!CryptoAuth_encrypt(ctx->sess, msg));
+    Assert_true(!TestCa_encrypt(ctx->sess, msg));
 
     char* actual = Hex_print(msg->bytes, msg->length, alloc);
     if (CString_strcmp(actual, expectedOutput)) {
@@ -118,33 +93,33 @@ static void testHello(uint8_t* password, uint8_t* expectedOutput)
     Allocator_free(alloc);
 }
 
-static void helloNoAuth()
+static void helloNoAuth(enum TestCa_Config cfg)
 {
     testHello(NULL,
         "00000000007691d3802a9d047c400000497a185dabda71739c1f35465fac3448"
         "b92a0c36ebff1cf7050383c91e7d56ec2336c09739fa8e91d8dc5bec63e8fad0"
         "74bee22a90642a6b4188f374afd90ccc97bb61873b5d8a3b4a6071b60b26a8c7"
         "2d6484634df315c4d3ad63de42fe3e4ebfd83bcdab2e1f5f40dc5a08eda4e6c6"
-        "b7067d3b");
+        "b7067d3b", cfg);
 }
 
-static void helloWithAuth()
+static void helloWithAuth(enum TestCa_Config cfg)
 {
     testHello("password",
         "0000000001641c99f7719f5700000000497a185dabda71739c1f35465fac3448"
         "b92a0c36ebff1cf7050383c91e7d56ec2336c09739fa8e91d8dc5bec63e8fad0"
         "74bee22a90642a6b022e089e0550ca84b86884af6a0263fa5fff9ba07583aea4"
         "acb000dbe4115623cf335c63981b9645b6c89fbdc3ad757744879751de0f215d"
-        "2479131d");
+        "2479131d", cfg);
 }
 
-static void receiveHelloWithNoAuth()
+static void receiveHelloWithNoAuth(enum TestCa_Config cfg)
 {
     uint8_t herPublic[32];
     Assert_true(Hex_decode(herPublic, 32,
         "847c0d2c375234f365e660955187a3735a0f7613d1609d3a6a4d8c53aeaa5a22", 64) > 0);
     struct Allocator* alloc = MallocAllocator_new(1<<20);
-    struct Context* ctx = setUp(PRIVATEKEY, herPublic, NULL, alloc);
+    struct Context* ctx = setUp(PRIVATEKEY, herPublic, NULL, alloc, cfg);
     struct Message* msg = Message_new(132, 0, alloc);
     Assert_true(Hex_decode(msg->bytes, msg->length,
         "0000000000ffffffffffffff7fffffffffffffffffffffffffffffffffffffff"
@@ -153,14 +128,14 @@ static void receiveHelloWithNoAuth()
         "3c76d313b767a10aca584ca0b979dee990a737da7d68366fa3846d43d541de91"
         "29ea3e12", 132*2) > 0);
 
-    Assert_true(!CryptoAuth_decrypt(ctx->sess, msg));
+    Assert_true(!TestCa_decrypt(ctx->sess, msg));
     Assert_true(msg->length == HELLOWORLDLEN);
     Assert_true(Bits_memcmp(HELLOWORLD, msg->bytes, HELLOWORLDLEN) == 0);
     Allocator_free(alloc);
     //printf("bytes=%s  length=%u\n", finalOut->bytes, finalOut->length);
 }
 
-static void repeatHello()
+static void repeatHello(enum TestCa_Config cfg)
 {
     uint8_t* expectedOutput =
         "0000000101641c99f7719f5700000000a693a9fd3f0e27e81ab1100b57b37259"
@@ -170,16 +145,16 @@ static void repeatHello()
         "24e7e550";
 
     struct Allocator* alloc = MallocAllocator_new(1<<20);
-    struct Context* ctx = setUp(NULL, HERPUBKEY, "password", alloc);
+    struct Context* ctx = setUp(NULL, HERPUBKEY, "password", alloc, cfg);
     struct Message* msg = Message_new(0, CryptoHeader_SIZE + HELLOWORLDLEN, alloc);
     Er_assert(Message_epush(msg, HELLOWORLD, HELLOWORLDLEN));
 
-    Assert_true(!CryptoAuth_encrypt(ctx->sess, msg));
+    Assert_true(!TestCa_encrypt(ctx->sess, msg));
 
     Message_reset(msg);
     Er_assert(Message_epush(msg, HELLOWORLD, HELLOWORLDLEN));
 
-    Assert_true(!CryptoAuth_encrypt(ctx->sess, msg));
+    Assert_true(!TestCa_encrypt(ctx->sess, msg));
 
     char* actual = Hex_print(msg->bytes, msg->length, alloc);
     if (CString_strcmp(actual, expectedOutput)) {
@@ -190,38 +165,46 @@ static void repeatHello()
     Allocator_free(alloc);
 }
 
-static void testGetUsers()
+static void testGetUsers(enum TestCa_Config cfg)
 {
     struct Allocator* allocator = MallocAllocator_new(1<<20);
     struct EventBase* base = EventBase_new(allocator);
-    struct CryptoAuth* ca =
-        CryptoAuth_new(allocator, NULL, base, NULL, evilRandom(allocator, NULL));
-    struct StringList* users = NULL;
+    TestCa_t* ca = TestCa_new(allocator, NULL, base, NULL, evilRandom(allocator, NULL), cfg);
+    RTypes_StrList_t* users = NULL;
 
-    users = CryptoAuth_getUsers(ca, allocator);
-    Assert_true(users->length == 0);
+    users = TestCa_getUsers(ca, allocator);
+    Assert_true(users->len == 0);
 
-    CryptoAuth_addUser(String_CONST("pass1"), String_CONST("user1"), ca);
-    users = CryptoAuth_getUsers(ca, allocator);
-    Assert_true(users->length == 1);
-    Assert_true(String_equals(String_CONST("user1"), StringList_get(users,0)));
+    TestCa_addUser_ipv6(String_CONST("pass1"), String_CONST("user1"), NULL, ca);
+    users = TestCa_getUsers(ca, allocator);
+    Assert_true(users->len == 1);
+    Assert_true(String_equals(String_CONST("user1"), users->items[0]));
 
-    CryptoAuth_addUser(String_CONST("pass2"), String_CONST("user2"), ca);
-    users = CryptoAuth_getUsers(ca, allocator);
-    Assert_true(users->length == 2);
-    Assert_true(String_equals(String_CONST("user2"),StringList_get(users,1)));
-    Assert_true(String_equals(String_CONST("user1"),StringList_get(users,0)));
+    TestCa_addUser_ipv6(String_CONST("pass2"), String_CONST("user2"), NULL, ca);
+    users = TestCa_getUsers(ca, allocator);
+    Assert_true(users->len == 2);
+    Assert_true(String_equals(String_CONST("user2"), users->items[1]));
+    Assert_true(String_equals(String_CONST("user1"), users->items[0]));
 
     Allocator_free(allocator);
 }
 
+static void iteration(enum TestCa_Config cfg)
+{
+    testGetUsers(cfg);
+    helloNoAuth(cfg);
+    helloWithAuth(cfg);
+    receiveHelloWithNoAuth(cfg);
+    repeatHello(cfg);
+}
+
 int main()
 {
-    testGetUsers();
-    helloNoAuth();
-    helloWithAuth();
-    receiveHelloWithNoAuth();
-    encryptRndNonceTest();
-    repeatHello();
+    iteration(TestCa_Config_OLD);
+    //iteration(TestCa_Config_OLD_NEW);
+
+    // This will always fail because we are expecting particular results
+    // which are specific to the old CryptoAuth
+    // iteration(TestCa_Config_NOISE);
     return 0;
 }

+ 252 - 0
crypto/test/TestCa.c

@@ -0,0 +1,252 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#include "crypto/test/TestCa.h"
+#include "crypto/CryptoAuth.h"
+#include "rust/cjdns_sys/Rffi.h"
+
+struct TestCa_s {
+    Rffi_CryptoAuth2_t* ca2;
+    struct CryptoAuth* ca;
+    bool noise;
+};
+struct TestCa_Session_s {
+    Rffi_CryptoAuth2_Session_t* s2;
+    struct CryptoAuth_Session* s;
+};
+
+TestCa_t* TestCa_new(
+    Allocator_t *allocator,
+    const uint8_t *privateKey,
+    struct EventBase* eventBase,
+    struct Log* logger,
+    struct Random* rand,
+    enum TestCa_Config cfg)
+{
+    TestCa_t* out = Allocator_calloc(allocator, sizeof(TestCa_t), 1);
+    if (cfg == TestCa_Config_OLD || cfg == TestCa_Config_OLD_NEW) {
+        out->ca = CryptoAuth_new(allocator, privateKey, eventBase, logger, rand);
+    }
+    if (cfg == TestCa_Config_OLD_NEW || cfg == TestCa_Config_NOISE) {
+        out->ca2 = Rffi_CryptoAuth2_new(allocator, privateKey);
+    }
+    if (cfg == TestCa_Config_NOISE) {
+        out->noise = true;
+    }
+    return out;
+}
+
+int TestCa_addUser_ipv6(
+    String_t *password,
+    String_t *login,
+    uint8_t *ipv6,
+    TestCa_t *ca)
+{
+    int ret = 0;
+    if (ca->ca) {
+        ret = CryptoAuth_addUser_ipv6(password, login, ipv6, ca->ca);
+    }
+    if (ca->ca2) {
+        int ret2 = Rffi_CryptoAuth2_addUser_ipv6(password, login, ipv6, ca->ca2);
+        if (ca->ca) {
+            Assert_true(ret == ret2);
+        }
+        return ret2;
+    }
+    return ret;
+}
+
+int TestCa_removeUsers(TestCa_t* ca, String_t* user)
+{
+    int i1 = 0;
+    if (ca->ca) {
+        i1 = CryptoAuth_removeUsers(ca->ca, user);
+    }
+    if (ca->ca2) {
+        int i2 = Rffi_CryptoAuth2_removeUsers(ca->ca2, user);
+        if (ca->ca) {
+            Assert_true(i1 == i2);
+        }
+        return i2;
+    }
+    return i1;
+}
+
+RTypes_StrList_t* TestCa_getUsers(const TestCa_t *ca, Allocator_t *alloc)
+{
+    RTypes_StrList_t* l1 = NULL;
+    if (ca->ca) {
+        l1 = CryptoAuth_getUsers(ca->ca, alloc);
+    }
+    if (ca->ca2) {
+        RTypes_StrList_t* l2 = Rffi_CryptoAuth2_getUsers(ca->ca2, alloc);
+        Assert_true(l1->len == l2->len);
+        for (uintptr_t i = 0; i < l1->len; i++) {
+            Assert_true(String_equals(l1->items[i], l2->items[i]));
+        }
+        return l2;
+    }
+    return l1;
+}
+
+TestCa_Session_t* TestCa_newSession(
+    TestCa_t *ca,
+    Allocator_t *alloc,
+    const uint8_t *herPublicKey,
+    bool requireAuth,
+    char *name,
+    bool useNoise)
+{
+    TestCa_Session_t* out = Allocator_calloc(alloc, sizeof(TestCa_Session_t), 1);
+    if (ca->ca) {
+        out->s = CryptoAuth_newSession(ca->ca, alloc, herPublicKey, requireAuth, name);
+    }
+    if (ca->ca2) {
+        out->s2 = Rffi_CryptoAuth2_newSession(
+            ca->ca2, alloc, herPublicKey, requireAuth, name, ca->noise && useNoise);
+    }
+    return out;
+}
+
+int TestCa_encrypt(TestCa_Session_t* sess, Message_t *msg)
+{
+    Message_t* m2 = NULL;
+    if (sess->s2) {
+        if (sess->s) {
+            m2 = Message_clone(msg, msg->alloc);
+        } else {
+            m2 = msg;
+            msg = NULL;
+        }
+    }
+    int i1 = 0;
+    if (sess->s) {
+        i1 = CryptoAuth_encrypt(sess->s, msg);
+    }
+    if (sess->s2) {
+        int i2 = Rffi_CryptoAuth2_encrypt(sess->s2, m2);
+        if (sess->s) {
+            Assert_true(i2 == i1);
+            Assert_true(msg->length == m2->length);
+            Assert_true(!Bits_memcmp(msg->bytes, m2->bytes, msg->length));
+        }
+        return i2;
+    }
+    return i1;
+}
+
+int TestCa_decrypt(TestCa_Session_t *sess, Message_t *msg)
+{
+    Message_t* m2 = NULL;
+    if (sess->s2) {
+        if (sess->s) {
+            m2 = Message_clone(msg, msg->alloc);
+        } else {
+            m2 = msg;
+            msg = NULL;
+        }
+    }
+    int i1 = 0;
+    if (sess->s) {
+        i1 = CryptoAuth_decrypt(sess->s, msg);
+    }
+    if (sess->s2) {
+        int i2 = Rffi_CryptoAuth2_decrypt(sess->s2, m2);
+        if (sess->s) {
+            Assert_true(i2 == i1);
+            Assert_true(msg->length == m2->length);
+            Assert_true(!Bits_memcmp(msg->bytes, m2->bytes, msg->length));
+        }
+        return i2;
+    }
+    return i1;
+}
+
+void TestCa_setAuth(const String_t* password, const String_t* login, TestCa_Session_t* sess)
+{
+    if (sess->s) {
+        CryptoAuth_setAuth(password, login, sess->s);
+    }
+    if (sess->s2) {
+        Rffi_CryptoAuth2_setAuth(password, login, sess->s2);
+    }
+}
+
+void TestCa_resetIfTimeout(TestCa_Session_t* sess)
+{
+    if (sess->s) {
+        CryptoAuth_resetIfTimeout(sess->s);
+    }
+    if (sess->s2) {
+        Rffi_CryptoAuth2_resetIfTimeout(sess->s2);
+    }
+}
+
+void TestCa_reset(TestCa_Session_t* sess)
+{
+    if (sess->s) {
+        CryptoAuth_reset(sess->s);
+    }
+    if (sess->s2) {
+        Rffi_CryptoAuth2_reset(sess->s2);
+    }
+}
+
+RTypes_CryptoAuth_State_t TestCa_getState(TestCa_Session_t* sess)
+{
+    RTypes_CryptoAuth_State_t st = 0;
+    if (sess->s) {
+        st = CryptoAuth_getState(sess->s);
+    }
+    if (sess->s2) {
+        RTypes_CryptoAuth_State_t st2 = Rffi_CryptoAuth2_getState(sess->s2);
+        if (sess->s) {
+            Assert_true(st2 == st);
+        }
+        return st2;
+    }
+    return st;
+}
+
+void TestCa_getHerPubKey(TestCa_Session_t* sess, uint8_t* buf)
+{
+    uint8_t hpk1[32];
+    if (sess->s) {
+        CryptoAuth_getHerPubKey(sess->s, hpk1);
+    }
+    if (sess->s2) {
+        Rffi_CryptoAuth2_getHerPubKey(sess->s2, buf);
+        if (sess->s) {
+            Assert_true(!Bits_memcmp(hpk1, buf, 32));
+        }
+        return;
+    }
+    Bits_memcpy(buf, hpk1, 32);
+}
+
+void TestCa_getPubKey(TestCa_t *ca, uint8_t* buf)
+{
+    uint8_t pk1[32];
+    if (ca->ca) {
+        CryptoAuth_getPubKey(ca->ca, pk1);
+    }
+    if (ca->ca2) {
+        Rffi_CryptoAuth2_getPubKey(ca->ca2, buf);
+        if (ca->ca) {
+            Assert_true(!Bits_memcmp(pk1, buf, 32));
+        }
+        return;
+    }
+    Bits_memcpy(buf, pk1, 32);
+}

+ 78 - 0
crypto/test/TestCa.h

@@ -0,0 +1,78 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef TESTCA_H
+#define TESTCA_H
+
+#include "benc/String.h"
+#include "rust/cjdns_sys/RTypes.h"
+#include "util/events/EventBase.h"
+#include "crypto/random/Random.h"
+#include "util/Linker.h"
+Linker_require("crypto/test/TestCa.c")
+
+typedef struct TestCa_s TestCa_t;
+typedef struct TestCa_Session_s TestCa_Session_t;
+
+enum TestCa_Config {
+    TestCa_Config_OLD,
+    TestCa_Config_OLD_NEW,
+    TestCa_Config_NOISE
+};
+
+TestCa_t* TestCa_new(
+    Allocator_t *allocator,
+    const uint8_t *privateKey,
+    struct EventBase* eventBase,
+    struct Log* logger,
+    struct Random* rand,
+    enum TestCa_Config cfg);
+
+int TestCa_addUser_ipv6(
+    String_t *password,
+    String_t *login,
+    uint8_t *ipv6,
+    TestCa_t *ca);
+
+int TestCa_removeUsers(TestCa_t* context, String_t* user);
+
+RTypes_StrList_t* TestCa_getUsers(const TestCa_t *ca, Allocator_t *alloc);
+
+TestCa_Session_t * TestCa_newSession(
+    TestCa_t *ca,
+    Allocator_t *alloc,
+    const uint8_t *herPublicKey,
+    bool requireAuth,
+    char *name,
+    bool useNoise);
+
+int TestCa_encrypt(TestCa_Session_t *session, Message_t *msg);
+
+int TestCa_decrypt(TestCa_Session_t *sess, Message_t *msg);
+
+void TestCa_setAuth(const String_t *password, const String_t *login, TestCa_Session_t *caSession);
+
+void TestCa_resetIfTimeout(TestCa_Session_t *session);
+
+void TestCa_reset(TestCa_Session_t *session);
+
+RTypes_CryptoAuth_State_t TestCa_getState(TestCa_Session_t *session);
+
+void TestCa_getHerPubKey(TestCa_Session_t *session, uint8_t* buf);
+
+void TestCa_getPubKey(
+    TestCa_t *ca,
+    uint8_t* buf);
+
+#endif

+ 2 - 8
do

@@ -7,13 +7,7 @@ if test "x$CARGO" = "x"; then
     printf "See https://rustup.rs/ for install instructions\n"
     exit 1
 fi
-$CARGO build --release
-./target/release/testcjdroute all >/dev/null
+RUSTFLAGS="$RUSTFLAGS -g" $CARGO build --release
+RUST_BACKTRACE=1 ./target/release/testcjdroute all >/dev/null
 mv ./target/release/cjdroute ./
-mv ./target/release/makekeys ./
-mv ./target/release/mkpasswd ./
-mv ./target/release/privatetopublic ./
-mv ./target/release/publictoip6 ./
-mv ./target/release/randombytes ./
-mv ./target/release/sybilsim ./
 printf "\x1b[1;32mBuild completed successfully, type ./cjdroute to begin setup.\x1b[0m\n"

+ 1 - 1
interface/test/RustIface_test.c

@@ -86,7 +86,7 @@ int main()
     Identity_set(ctx);
     ctx->outside.send = sendOutside;
     ctx->inside.send = sendInside;
-    Rffi_IfWrapper_t wrapper = Rffi_testwrapper_create(alloc);
+    RTypes_IfWrapper_t wrapper = Rffi_testwrapper_create(alloc);
     Iface_plumb(&ctx->inside, wrapper.internal);
     Iface_plumb(&ctx->outside, wrapper.external);
 

+ 10 - 3
net/Benchmark.c

@@ -73,11 +73,15 @@ static void cryptoAuth(struct Context* ctx)
     struct Allocator* alloc = Allocator_child(ctx->alloc);
     struct CryptoAuth* ca1 = CryptoAuth_new(alloc, NULL, ctx->base, ctx->log, ctx->rand);
     struct CryptoAuth* ca2 = CryptoAuth_new(alloc, NULL, ctx->base, ctx->log, ctx->rand);
+    uint8_t ca1Pub[32];
+    CryptoAuth_getPubKey(ca1, ca1Pub);
+    uint8_t ca2Pub[32];
+    CryptoAuth_getPubKey(ca2, ca2Pub);
 
     struct CryptoAuth_Session* sess1 =
-        CryptoAuth_newSession(ca1, alloc, ca2->publicKey, false, "bench");
+        CryptoAuth_newSession(ca1, alloc, ca2Pub, false, "bench");
     struct CryptoAuth_Session* sess2 =
-        CryptoAuth_newSession(ca2, alloc, ca1->publicKey, false, "bench");
+        CryptoAuth_newSession(ca2, alloc, ca1Pub, false, "bench");
 
     int size = 1500;
     int count = 100000;
@@ -167,10 +171,13 @@ static void switching(struct Context* ctx)
 
     CryptoAuth_addUser(String_CONST("abcdefg123"), String_CONST("TEST"), bob->ca);
 
+    uint8_t bobPub[32];
+    CryptoAuth_getPubKey(bob->ca, bobPub);
+
     // Client has pubKey and passwd for the server.
     int ret = InterfaceController_bootstrapPeer(alice->ifController,
                                                 aliceIci->ifNum,
-                                                bob->ca->publicKey,
+                                                bobPub,
                                                 Sockaddr_LOOPBACK,
                                                 String_CONST("abcdefg123"),
                                                 NULL,

+ 25 - 21
net/InterfaceController.c

@@ -221,6 +221,8 @@ struct InterfaceController_pvt
 
     struct Headers_Beacon beacon;
 
+    uint8_t ourPubKey[32];
+
     Identity
 };
 
@@ -349,14 +351,16 @@ static void linkState(void* vic)
         for (uint32_t i = 0; i < ici->peerMap.count; i++) {
             struct Peer* ep = ici->peerMap.values[i];
 
-            uint32_t drops = ep->caSession->replayProtector.lostPackets;
+            RTypes_CryptoStats_t stats;
+            CryptoAuth_stats(ep->caSession, &stats);
+            uint32_t drops = stats.lost_packets;
             uint64_t newDrops = 0;
             // We're checking uint32 rollover here
             if (drops > ep->_lastDrops) { newDrops = drops - ep->_lastDrops; }
             ep->_lastDrops = drops;
             ep->lastDrops += newDrops;
 
-            uint32_t packets = ep->caSession->replayProtector.baseOffset;
+            uint32_t packets = stats.received_packets;
             uint64_t newPackets = 0;
             if (packets > ep->_lastPackets) { newPackets = packets - ep->_lastPackets; }
             ep->_lastPackets = packets;
@@ -498,7 +502,7 @@ static Iface_DEFUN receivedPostCryptoAuth(struct Message* msg,
         ep->state = caState;
         SwitchCore_setInterfaceState(&ep->switchIf, SwitchCore_setInterfaceState_ifaceState_UP);
 
-        Bits_memcpy(ep->addr.key, ep->caSession->herPublicKey, 32);
+        CryptoAuth_getHerPubKey(ep->caSession, ep->addr.key);
         Address_getPrefix(&ep->addr);
 
         if (caState != CryptoAuth_State_ESTABLISHED) {
@@ -648,7 +652,7 @@ static Iface_DEFUN handleBeacon(struct Message* msg, struct InterfaceController_
     if (!AddressCalc_validAddress(addr.ip6.bytes)) {
         Log_debug(ic->logger, "handleBeacon invalid key [%s]", printedAddr->bytes);
         return Error(INVALID);
-    } else if (!Bits_memcmp(ic->ca->publicKey, addr.key, 32)) {
+    } else if (!Bits_memcmp(ic->ourPubKey, addr.key, 32)) {
         // receive beacon from self, drop silent
         return Error(NONE);
     }
@@ -739,6 +743,9 @@ static Iface_DEFUN handleUnexpectedIncoming(struct Message* msg,
         // which is not a setup packet will be summarily dropped.
         return Error(INVALID);
     }
+    if (Bits_isZero(ch->publicKey, 32)) {
+        return Error(INVALID);
+    }
 
     struct Allocator* epAlloc = Allocator_child(ici->alloc);
     lladdr = Sockaddr_clone(lladdr, epAlloc);
@@ -757,7 +764,6 @@ static Iface_DEFUN handleUnexpectedIncoming(struct Message* msg,
         Allocator_free(epAlloc);
         return Error(AUTHENTICATION);
     }
-    Assert_true(!Bits_isZero(ep->caSession->herPublicKey, 32));
     Assert_true(Map_EndpointsBySockaddr_indexForKey(&lladdr, &ici->peerMap) == -1);
     int index = Map_EndpointsBySockaddr_put(&lladdr, &ep, &ici->peerMap);
     Assert_true(index >= 0);
@@ -779,8 +785,8 @@ static Iface_DEFUN handleUnexpectedIncoming(struct Message* msg,
     ep->timeOfLastMessage =
         Time_currentTimeMilliseconds(ic->eventBase) - ic->pingAfterMilliseconds - 1;
 
-    Bits_memcpy(ep->addr.key, ep->caSession->herPublicKey, 32);
-    Bits_memcpy(ep->addr.ip6.bytes, ep->caSession->herIp6, 16);
+    CryptoAuth_getHerPubKey(ep->caSession, ep->addr.key);
+    CryptoAuth_getHerIp6(ep->caSession, ep->addr.ip6.bytes);
     Log_info(ic->logger, "Added peer [%s] from incoming message",
         Address_toString(&ep->addr, msg->alloc)->bytes);
 
@@ -1002,7 +1008,7 @@ int InterfaceController_bootstrapPeer(struct InterfaceController* ifc,
 
     uint8_t ip6[16];
     AddressCalc_addressForPublicKey(ip6, herPublicKey);
-    if (!AddressCalc_validAddress(ip6) || !Bits_memcmp(ic->ca->publicKey, herPublicKey, 32)) {
+    if (!AddressCalc_validAddress(ip6) || !Bits_memcmp(ic->ourPubKey, herPublicKey, 32)) {
         return InterfaceController_bootstrapPeer_BAD_KEY;
     }
 
@@ -1026,11 +1032,8 @@ int InterfaceController_bootstrapPeer(struct InterfaceController* ifc,
     Allocator_onFree(alloc, freeAlloc, epAlloc);
 
     ep->peerLink = PeerLink_new(ic->eventBase, epAlloc);
-    ep->caSession = CryptoAuth_newSession(ic->ca, epAlloc, herPublicKey, false, "outer");
+    ep->caSession = CryptoAuth_newSession(ic->ca, epAlloc, herPublicKey, false, user);
     CryptoAuth_setAuth(password, login, ep->caSession);
-    if (user) {
-        ep->caSession->displayName = String_clone(user, epAlloc);
-    }
 
     ep->switchIf.send = sendFromSwitch;
 
@@ -1092,12 +1095,11 @@ int InterfaceController_getPeerStats(struct InterfaceController* ifController,
             s->timeOfLastMessage = peer->timeOfLastMessage;
             s->state = peer->state;
             s->isIncomingConnection = peer->isIncomingConnection;
-            if (peer->caSession->displayName) {
-                s->user = String_clone(peer->caSession->displayName, alloc);
-            }
-            struct ReplayProtector* rp = &peer->caSession->replayProtector;
-            s->duplicates = rp->duplicates;
-            s->receivedOutOfRange = rp->receivedOutOfRange;
+            s->user = CryptoAuth_getName(peer->caSession, alloc);
+            RTypes_CryptoStats_t stats;
+            CryptoAuth_stats(peer->caSession, &stats);
+            s->duplicates = stats.duplicate_packets;
+            s->receivedOutOfRange = stats.received_unexpected;
 
             struct PeerLink_Kbps kbps;
             PeerLink_kbps(peer->peerLink, &kbps);
@@ -1125,7 +1127,7 @@ void InterfaceController_resetPeering(struct InterfaceController* ifController,
         struct InterfaceController_Iface_pvt* ici = ArrayList_OfIfaces_get(ic->icis, j);
         for (int i = 0; i < (int)ici->peerMap.count; i++) {
             struct Peer* peer = ici->peerMap.values[i];
-            if (!herPublicKey || !Bits_memcmp(herPublicKey, peer->caSession->herPublicKey, 32)) {
+            if (!herPublicKey || !Bits_memcmp(herPublicKey, peer->addr.key, 32)) {
                 CryptoAuth_reset(peer->caSession);
             }
         }
@@ -1142,7 +1144,7 @@ int InterfaceController_disconnectPeer(struct InterfaceController* ifController,
         struct InterfaceController_Iface_pvt* ici = ArrayList_OfIfaces_get(ic->icis, j);
         for (int i = 0; i < (int)ici->peerMap.count; i++) {
             struct Peer* peer = ici->peerMap.values[i];
-            if (!Bits_memcmp(herPublicKey, peer->caSession->herPublicKey, 32)) {
+            if (!Bits_memcmp(herPublicKey, peer->addr.key, 32)) {
                 Allocator_free(peer->alloc);
                 return 0;
             }
@@ -1227,7 +1229,9 @@ struct InterfaceController* InterfaceController_new(struct CryptoAuth* ca,
     if (ret) {
         Log_warn(logger, "CryptoAuth_addUser() returned [%d]", ret);
     }
-    Bits_memcpy(out->beacon.publicKey, ca->publicKey, 32);
+
+    CryptoAuth_getPubKey(ca, out->ourPubKey);
+    Bits_memcpy(out->beacon.publicKey, out->ourPubKey, 32);
     out->beacon.version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL);
 
     Timeout_setTimeout(beaconInterval, out, BEACON_INTERVAL, eventBase, alloc);

+ 5 - 3
net/NetCore.c

@@ -44,10 +44,12 @@ struct NetCore* NetCore_new(uint8_t* privateKey,
     nc->log = log;
 
     struct CryptoAuth* ca = nc->ca = CryptoAuth_new(alloc, privateKey, base, log, rand);
-    struct EventEmitter* ee = nc->ee = EventEmitter_new(alloc, log, ca->publicKey);
+    uint8_t ourPubKey[32];
+    CryptoAuth_getPubKey(ca, ourPubKey);
+    struct EventEmitter* ee = nc->ee = EventEmitter_new(alloc, log, ourPubKey);
 
     struct Address* myAddress = nc->myAddress = Allocator_calloc(alloc, sizeof(struct Address), 1);
-    Bits_memcpy(myAddress->key, ca->publicKey, 32);
+    Bits_memcpy(myAddress->key, ourPubKey, 32);
     Address_getPrefix(myAddress);
     myAddress->protocolVersion = Version_CURRENT_PROTOCOL;
     myAddress->path = 1;
@@ -61,7 +63,7 @@ struct NetCore* NetCore_new(uint8_t* privateKey,
     Iface_plumb(&sm->insideIf, &upper->sessionManagerIf);
 
     struct ControlHandler* controlHandler = nc->controlHandler =
-        ControlHandler_new(alloc, log, ee, ca->publicKey);
+        ControlHandler_new(alloc, log, ee, ourPubKey);
     Iface_plumb(&controlHandler->coreIf, &upper->controlHandlerIf);
 
     struct SwitchPinger* sp = nc->sp = SwitchPinger_new(base, rand, log, myAddress, alloc);

+ 21 - 11
net/SessionManager.c

@@ -62,6 +62,7 @@ struct SessionManager_pvt
     struct CryptoAuth* cryptoAuth;
     struct EventBase* eventBase;
     uint32_t firstHandle;
+    uint8_t ourPubKey[32];
     Identity
 };
 
@@ -84,7 +85,9 @@ struct SessionManager_Session_pvt
         uint8_t path[20];                                                              \
         AddrTools_printPath(path, label);                                              \
         uint8_t ip[40];                                                                \
-        AddrTools_printIp(ip, session->pub.caSession->herIp6);                         \
+        uint8_t ipb[16];                                                               \
+        CryptoAuth_getHerIp6(session->pub.caSession, ipb);                             \
+        AddrTools_printIp(ip, ipb);                                                    \
         Log_debug(logger, "ver[%u] send[%d] recv[%u] ip[%s] path[%s] " message,        \
                   session->pub.version,                                                \
                   session->pub.sendHandle,                                             \
@@ -103,8 +106,10 @@ struct SessionManager_Session_pvt
         if (!Defined(Log_DEBUG)) { break; }                                            \
         uint8_t sendPath[20];                                                          \
         uint8_t ip[40];                                                                \
+        uint8_t ipb[16];                                                               \
+        CryptoAuth_getHerIp6(session->pub.caSession, ipb);                             \
+        AddrTools_printIp(ip, ipb);                                                    \
         AddrTools_printPath(sendPath, (label));                                        \
-        AddrTools_printIp(ip, (session)->pub.caSession->herIp6);                       \
         Log_debug((logger), "Session[%p] [%s.%s] " message,                            \
                   (void*)session,                                                      \
                   sendPath,                                                            \
@@ -126,8 +131,8 @@ static void sendSession(struct SessionManager_Session_pvt* sess,
         .metric_be = Endian_bigEndianToHost32(path->metric),
         .version_be = Endian_hostToBigEndian32(sess->pub.version)
     };
-    Bits_memcpy(session.ip6, sess->pub.caSession->herIp6, 16);
-    Bits_memcpy(session.publicKey, sess->pub.caSession->herPublicKey, 32);
+    CryptoAuth_getHerPubKey(sess->pub.caSession, session.publicKey);
+    CryptoAuth_getHerIp6(sess->pub.caSession, session.ip6);
 
     struct Allocator* alloc = Allocator_child(sess->alloc);
     struct Message* msg = Message_new(0, PFChan_Node_SIZE + 512, alloc);
@@ -142,7 +147,8 @@ static inline void check(struct SessionManager_pvt* sm, int mapIndex)
 {
     struct SessionManager_Session_pvt* ssp = Identity_check(sm->ifaceMap.values[mapIndex]);
     if (ssp->foundKey) { return; }
-    uint8_t* herPubKey = ssp->pub.caSession->herPublicKey;
+    uint8_t herPubKey[32];
+    CryptoAuth_getHerPubKey(ssp->pub.caSession, herPubKey);
     if (!Bits_isZero(herPubKey, 32)) {
         uint8_t ip6[16];
         AddressCalc_addressForPublicKey(ip6, herPubKey);
@@ -447,7 +453,7 @@ static Iface_DEFUN incomingFromSwitchIf(struct Message* msg, struct Iface* iface
             return Error(INVALID);
         }
 
-        if (!Bits_memcmp(caHeader->publicKey, sm->cryptoAuth->publicKey, 32)) {
+        if (!Bits_memcmp(caHeader->publicKey, sm->ourPubKey, 32)) {
             Log_debug(sm->log, "DROP Handshake from 'ourselves'");
             return Error(INVALID);
         }
@@ -507,8 +513,8 @@ static Iface_DEFUN incomingFromSwitchIf(struct Message* msg, struct Iface* iface
     }
 
     header->version_be = Endian_hostToBigEndian32(session->pub.version);
-    Bits_memcpy(header->ip6, session->pub.caSession->herIp6, 16);
-    Bits_memcpy(header->publicKey, session->pub.caSession->herPublicKey, 32);
+    CryptoAuth_getHerPubKey(session->pub.caSession, header->publicKey);
+    CryptoAuth_getHerIp6(session->pub.caSession, header->ip6);
 
     header->unused = 0;
     header->flags = RouteHeader_flags_INCOMING;
@@ -544,8 +550,8 @@ static void unsetupSession(struct SessionManager_pvt* sm, struct SessionManager_
     Assert_true(n.path_be);
     n.version_be = Endian_hostToBigEndian32(sess->pub.version);
     n.metric_be = Endian_bigEndianToHost32(sess->pub.paths[0].metric);
-    Bits_memcpy(n.publicKey, sess->pub.caSession->herPublicKey, 32);
-    Bits_memcpy(n.ip6, sess->pub.caSession->herIp6, 16);
+    CryptoAuth_getHerPubKey(sess->pub.caSession, n.publicKey);
+    CryptoAuth_getHerIp6(sess->pub.caSession, n.ip6);
     Er_assert(Message_epush(eventMsg, &n, PFChan_Node_SIZE));
     Er_assert(Message_epush32be(eventMsg, 0xffffffff));
     Er_assert(Message_epush32be(eventMsg, PFChan_Core_UNSETUP_SESSION));
@@ -607,7 +613,9 @@ static void checkTimedOutSessions(struct SessionManager_pvt* sm)
             // Session is not in idle state and requires a search
             debugSession0(sm->log, sess, sess->pub.paths[0].label,
                 "it's been a while, triggering search");
-            triggerSearch(sm, sess->pub.caSession->herIp6, sess->pub.version);
+            uint8_t herIp6[16];
+            CryptoAuth_getHerIp6(sess->pub.caSession, herIp6);
+            triggerSearch(sm, herIp6, sess->pub.version);
             sess->pub.lastSearchTime = now;
         } else if (CryptoAuth_getState(sess->pub.caSession) < CryptoAuth_State_ESTABLISHED) {
             debugSession0(sm->log, sess, sess->pub.paths[0].label, "triggering unsetupSession");
@@ -888,6 +896,8 @@ struct SessionManager* SessionManager_new(struct Allocator* allocator,
     sm->pub.sessionSearchAfterMilliseconds =
         SessionManager_SESSION_SEARCH_AFTER_MILLISECONDS_DEFAULT;
 
+    CryptoAuth_getPubKey(cryptoAuth, sm->ourPubKey);
+
     sm->eventIf.send = incomingFromEventIf;
     EventEmitter_regCore(ee, &sm->eventIf, PFChan_Pathfinder_NODE);
     EventEmitter_regCore(ee, &sm->eventIf, PFChan_Pathfinder_SESSIONS);

+ 10 - 7
net/SessionManager_admin.c

@@ -72,21 +72,24 @@ static void outputSession(struct Context* context,
         return;
     }
 
+    struct Address addr;
+    CryptoAuth_getHerPubKey(session->caSession, addr.key);
+    Address_getPrefix(&addr);
     uint8_t printedAddr[40];
-    AddrTools_printIp(printedAddr, session->caSession->herIp6);
+    AddrTools_printIp(printedAddr, addr.ip6.bytes);
     Dict_putStringC(r, "ip6", String_new(printedAddr, alloc), alloc);
 
     String* state =
         String_new(CryptoAuth_stateString(CryptoAuth_getState(session->caSession)), alloc);
     Dict_putStringC(r, "state", state, alloc);
 
-    struct ReplayProtector* rp = &session->caSession->replayProtector;
-    Dict_putIntC(r, "duplicates", rp->duplicates, alloc);
-    Dict_putIntC(r, "lostPackets", rp->lostPackets, alloc);
-    Dict_putIntC(r, "receivedOutOfRange", rp->receivedOutOfRange, alloc);
+    RTypes_CryptoStats_t stats;
+    CryptoAuth_stats(&session->caSession, &stats);
+    Dict_putIntC(r, "duplicates", stats.duplicate_packets, alloc);
+    Dict_putIntC(r, "lostPackets", stats.lost_packets, alloc);
+    Dict_putIntC(r, "receivedOutOfRange", stats.received_unexpected, alloc);
+
 
-    struct Address addr;
-    Bits_memcpy(addr.key, session->caSession->herPublicKey, 32);
     addr.path = session->paths[0].label;
     addr.protocolVersion = session->version;
 

+ 1 - 2
rust/cjdns_sys/Cargo.toml

@@ -15,9 +15,8 @@ anyhow = "1.0"
 [build_dependencies]
 cc = "1.0"
 anyhow = "1.0"
-cbindgen = { version = "0.15", optional = true }
+cbindgen = { version = "0.16" }
 bindgen = { version = "0.55", optional = true }
 
 [features]
-generate-rffi = ["cbindgen"]
 generate-cffi = ["bindgen"]

+ 72 - 0
rust/cjdns_sys/RTypes.h

@@ -0,0 +1,72 @@
+#ifndef RTypes_H
+#define RTypes_H
+
+// This file is generated from src/rtypes.rs using cbindgen
+
+#include "RTypesPrefix.h"
+
+typedef enum {
+  /**
+   * New CryptoAuth session, has not sent or received anything
+   */
+  RTypes_CryptoAuth_State_t_Init = 0,
+  /**
+   * Sent a hello message, waiting for reply
+   */
+  RTypes_CryptoAuth_State_t_SentHello = 1,
+  /**
+   * Received a hello message, have not yet sent a reply
+   */
+  RTypes_CryptoAuth_State_t_ReceivedHello = 2,
+  /**
+   * Received a hello message, sent a key message, waiting for the session to complete
+   */
+  RTypes_CryptoAuth_State_t_SentKey = 3,
+  /**
+   * Sent a hello message, received a key message, may or may not have sent some data traffic
+   * but no data traffic has yet been received
+   */
+  RTypes_CryptoAuth_State_t_ReceivedKey = 4,
+  /**
+   * Received data traffic, session is in run state
+   */
+  RTypes_CryptoAuth_State_t_Established = 100,
+} RTypes_CryptoAuth_State_t;
+
+typedef struct {
+  Iface_t *internal;
+  Iface_t *external;
+} RTypes_IfWrapper_t;
+
+typedef struct {
+  uintptr_t len;
+  String_t **items;
+} RTypes_StrList_t;
+
+typedef struct {
+  /**
+   * Number of packets which were lost
+   */
+  uint64_t lost_packets;
+  /**
+   * Number of packets which were received but could not be validated
+   */
+  uint64_t received_unexpected;
+  /**
+   * Number of packets which were received (since last session setup)
+   */
+  uint64_t received_packets;
+  /**
+   * Number of packets which were received that were duplicates
+   */
+  uint64_t duplicate_packets;
+} RTypes_CryptoStats_t;
+
+typedef struct {
+  RTypes_IfWrapper_t a;
+  RTypes_StrList_t b;
+  RTypes_CryptoAuth_State_t c;
+  RTypes_CryptoStats_t d;
+} RTypes_ExportMe;
+
+#endif /* RTypes_H */

+ 7 - 0
rust/cjdns_sys/RTypesPrefix.h

@@ -0,0 +1,7 @@
+#ifndef RTYPESPREFIX_H
+#define RTYPESPREFIX_H
+
+#include "benc/String.h"
+#include "interface/Iface.h"
+
+#endif

+ 23 - 16
rust/cjdns_sys/Rffi.h

@@ -3,33 +3,24 @@
 
 // This file is generated from src/rffi.rs using cbindgen
 
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include "cffi.h"
+#include "RffiPrefix.h"
 
 typedef struct Rffi_CryptoAuth2_Session_t Rffi_CryptoAuth2_Session_t;
 
 typedef struct Rffi_CryptoAuth2_t Rffi_CryptoAuth2_t;
 
-typedef struct Vec_Vec_u8 Vec_Vec_u8;
+RTypes_IfWrapper_t Rffi_testwrapper_create(Allocator_t *a);
 
-typedef struct {
-  Iface_t *internal;
-  Iface_t *external;
-} Rffi_IfWrapper_t;
-
-Rffi_IfWrapper_t Rffi_testwrapper_create(Allocator_t *a);
-
-Rffi_IfWrapper_t Rffi_android_create(Allocator_t *a);
+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);
 
-Vec_Vec_u8 *Rffi_CryptoAuth2_getUsers(const Rffi_CryptoAuth2_t *ca, Allocator_t *alloc);
+int Rffi_CryptoAuth2_removeUsers(Rffi_CryptoAuth2_t *context, String_t *user);
+
+RTypes_StrList_t *Rffi_CryptoAuth2_getUsers(const Rffi_CryptoAuth2_t *ca, Allocator_t *alloc);
 
 Rffi_CryptoAuth2_t *Rffi_CryptoAuth2_new(Allocator_t *allocator, const uint8_t *privateKey);
 
@@ -37,7 +28,8 @@ Rffi_CryptoAuth2_Session_t *Rffi_CryptoAuth2_newSession(Rffi_CryptoAuth2_t *ca,
                                                         Allocator_t *alloc,
                                                         const uint8_t *herPublicKey,
                                                         bool requireAuth,
-                                                        char *name);
+                                                        char *name,
+                                                        bool useNoise);
 
 int Rffi_CryptoAuth2_encrypt(Rffi_CryptoAuth2_Session_t *session, Message_t *msg);
 
@@ -51,4 +43,19 @@ void Rffi_CryptoAuth2_resetIfTimeout(Rffi_CryptoAuth2_Session_t *session);
 
 void Rffi_CryptoAuth2_reset(Rffi_CryptoAuth2_Session_t *caSession);
 
+RTypes_CryptoAuth_State_t Rffi_CryptoAuth2_getState(Rffi_CryptoAuth2_Session_t *session);
+
+void Rffi_CryptoAuth2_getHerPubKey(const Rffi_CryptoAuth2_Session_t *session, uint8_t *pkOut);
+
+void Rffi_CryptoAuth2_getHerIp6(const Rffi_CryptoAuth2_Session_t *session, uint8_t *ipOut);
+
+String_t *Rffi_CryptoAuth2_getName(const Rffi_CryptoAuth2_Session_t *session, Allocator_t *alloc);
+
+void Rffi_CryptoAuth2_getPubKey(Rffi_CryptoAuth2_t *ca, uint8_t *pkOut);
+
+void Rffi_CryptoAuth2_stats(const Rffi_CryptoAuth2_Session_t *session,
+                            RTypes_CryptoStats_t *statsOut);
+
+void Rffi_panic(const char *msg);
+
 #endif /* rffi_H */

+ 7 - 0
rust/cjdns_sys/RffiPrefix.h

@@ -0,0 +1,7 @@
+#ifndef RFFIPREFIX_H
+#define RFFIPREFIX_H
+
+#include "rust/cjdns_sys/RTypes.h"
+#include "rust/cjdns_sys/cffi.h"
+
+#endif

+ 23 - 2
rust/cjdns_sys/build.rs

@@ -22,8 +22,28 @@ fn cfiles<P: AsRef<Path>>(out: &mut Vec<PathBuf>, path: P) -> Result<()> {
 
 fn main() -> Result<()> {
     // Generate C bindings from rust
-    #[cfg(feature = "generate-rffi")]
     {
+        println!("Generating rtypes");
+        let mut conf = cbindgen::Config::default();
+        conf.language = cbindgen::Language::C;
+        conf.autogen_warning =
+            Some("// This file is generated from src/rtypes.rs using cbindgen".to_owned());
+        conf.style = cbindgen::Style::Type;
+        conf.include_guard = Some("RTypes_H".to_owned());
+        conf.export.include = vec!["RTypes_ExportMe".to_owned()];
+        conf.no_includes = true;
+        conf.includes = vec!["RTypesPrefix.h".to_owned()];
+        conf.enumeration.prefix_with_name = true;
+        cbindgen::Builder::new()
+            .with_src("./src/rtypes.rs")
+            .with_config(conf)
+            .generate()
+            .expect("Unable to generate rtypes")
+            .write_to_file("RTypes.h");
+        println!("Generating rtypes done");
+
+        //
+
         println!("Generating rffi");
         let mut conf = cbindgen::Config::default();
         conf.language = cbindgen::Language::C;
@@ -31,7 +51,8 @@ fn main() -> Result<()> {
             Some("// This file is generated from src/rffi.rs using cbindgen".to_owned());
         conf.style = cbindgen::Style::Type;
         conf.include_guard = Some("rffi_H".to_owned());
-        conf.includes = vec!["cffi.h".to_owned()];
+        conf.no_includes = true;
+        conf.includes = vec!["RffiPrefix.h".to_owned()];
         cbindgen::Builder::new()
             .with_src("./src/rffi.rs")
             .with_config(conf)

+ 1 - 0
rust/cjdns_sys/cffi.h

@@ -15,6 +15,7 @@
 
 // This file is used to generate src/cffi.rs using bindgen
 
+#include "benc/String.h"
 #include "memory/Allocator.h"
 #include "memory/MallocAllocator.h"
 #include "interface/Iface.h"

+ 71 - 38
rust/cjdns_sys/src/crypto/crypto_auth.rs

@@ -14,6 +14,8 @@ use crate::crypto::keys::{IpV6, PrivateKey, PublicKey};
 use crate::crypto::random::Random;
 use crate::crypto::replay_protector::ReplayProtector;
 use crate::interface::wire::message::Message;
+use crate::rtypes::RTypes_CryptoAuth_State_t as State;
+use crate::rtypes::*;
 use crate::util::events::EventBase;
 
 pub struct CryptoAuth {
@@ -96,28 +98,6 @@ pub struct Session {
     context: Arc<CryptoAuth>,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum State {
-    /// New CryptoAuth session, has not sent or received anything
-    Init = 0,
-
-    /// Sent a hello message, waiting for reply
-    SentHello = 1,
-
-    /// Received a hello message, have not yet sent a reply
-    ReceivedHello = 2,
-
-    /// Received a hello message, sent a key message, waiting for the session to complete
-    SentKey = 3,
-
-    /// Sent a hello message, received a key message, may or may not have sent some data traffic
-    /// but no data traffic has yet been received
-    ReceivedKey = 4,
-
-    /// Received data traffic, session is in run state
-    Established = 100,
-}
-
 #[derive(Error, Debug, Clone, PartialEq, Eq)]
 pub enum AddUserError {
     #[error("Duplicate user")]
@@ -128,37 +108,52 @@ pub enum AddUserError {
 #[derive(Error, Debug, Clone, PartialEq, Eq)]
 pub enum DecryptErr {
     #[error("NONE")]
-    NONE = 0,
+    None = 0,
+
     #[error("RUNT")]
-    RUNT = 1,
+    Runt = 1,
+
     #[error("NO_SESSION")]
-    NO_SESSION = 2,
+    NoSession = 2,
+
     #[error("FINAL_HANDSHAKE_FAIL")]
-    FINAL_SHAKE_FAIL = 3,
+    FinalShakeFail = 3,
+
     #[error("FAILED_DECRYPT_RUN_MSG")]
-    FAILED_DECRYPT_RUN_MSG = 4,
+    FailedDecryptionRunMsg = 4,
+
     #[error("KEY_PKT_ESTABLISHED_SESSION")]
-    KEY_PKT_ESTABLISHED_SESSION = 5,
+    KeyPktEstablishedSession = 5,
+
     #[error("WRONG_PERM_PUBKEY")]
-    WRONG_PERM_PUBKEY = 6,
+    WrongPermPubkey = 6,
+
     #[error("IP_RESTRICTED")]
-    IP_RESTRICTED = 7,
+    IpRestricted = 7,
+
     #[error("AUTH_REQUIRED")]
-    AUTH_REQUIRED = 8,
+    AuthRequired = 8,
+
     #[error("UNRECOGNIZED_AUTH")]
-    UNRECOGNIZED_AUTH = 9,
+    UnrecognizedAuth = 9,
+
     #[error("STRAY_KEY")]
-    STRAY_KEY = 10,
+    StrayKey = 10,
+
     #[error("HANDSHAKE_DECRYPT_FAILED")]
-    HANDSHAKE_DECRYPT_FAILED = 11,
+    HandshakeDecryptFailed = 11,
+
     #[error("WISEGUY")]
-    WISEGUY = 12,
+    Wiseguy = 12,
+
     #[error("INVALID_PACKET")]
-    INVALID_PACKET = 13,
+    InvalidPacket = 13,
+
     #[error("REPLAY")]
-    REPLAY = 14,
+    Replay = 14,
+
     #[error("DECRYPT")]
-    DECRYPT = 15,
+    Decrypt = 15,
 }
 
 fn crypto_scalarmult_curve25519_base(pvt: &[u8; 32]) -> [u8; 32] {
@@ -327,6 +322,18 @@ impl SessionMut {
         }
     }
 
+    pub fn get_her_pubkey(&self) -> [u8; 32] {
+        self.her_public_key.0.clone()
+    }
+
+    pub fn get_her_ip6(&self) -> [u8; 16] {
+        self.her_ip6.0.clone()
+    }
+
+    pub fn get_name(&self) -> Option<String> {
+        self.display_name.clone()
+    }
+
     pub 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
@@ -379,9 +386,14 @@ impl Session {
         her_pub_key: PublicKey,
         require_auth: bool,
         display_name: Option<String>,
+        use_noise: bool,
     ) -> Self {
         let now = context.event_base.current_time_seconds();
 
+        if use_noise {
+            panic!("noise protocol not yet implemented");
+        }
+
         assert!(her_pub_key.is_non_zero());
         let her_ip6 = her_pub_key.address_for_public_key();
 
@@ -427,6 +439,27 @@ impl Session {
         self.m.read().unwrap().get_state()
     }
 
+    pub fn get_her_pubkey(&self) -> [u8; 32] {
+        self.m.read().unwrap().get_her_pubkey()
+    }
+
+    pub fn get_her_ip6(&self) -> [u8; 16] {
+        self.m.read().unwrap().get_her_ip6()
+    }
+
+    pub fn get_name(&self) -> Option<String> {
+        self.m.read().unwrap().get_name()
+    }
+
+    pub fn stats(&self) -> RTypes_CryptoStats_t {
+        // Stats come from the replay protector
+        let rp = self.replay_protector.lock().unwrap();
+        // RTypes_CryptoStats_t{
+        //     received_packets: rp.
+        // }
+        todo!()
+    }
+
     pub fn reset_if_timeout(&self) {
         self.m
             .write()

+ 1 - 0
rust/cjdns_sys/src/lib.rs

@@ -52,6 +52,7 @@ mod interface {
 
 mod cffi;
 mod rffi;
+mod rtypes;
 mod crypto {
     pub mod crypto_auth;
     mod crypto_header;

+ 77 - 37
rust/cjdns_sys/src/rffi.rs

@@ -7,32 +7,26 @@ use crate::crypto::keys::{IpV6, PrivateKey, PublicKey};
 use crate::external::interface::cif;
 use crate::external::memory::allocator;
 use crate::interface::wire::message::Message;
+use crate::rtypes::*;
 
-use std::os::raw::{c_char, c_int};
+use std::os::raw::{c_char, c_int, c_uchar};
 use std::sync::Arc;
 
 // This file is used to generate cbindings.h using cbindgen
 
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct Rffi_IfWrapper_t {
-    pub internal: *mut Iface_t,
-    pub external: *mut Iface_t,
-}
-
 #[no_mangle]
-pub unsafe extern "C" fn Rffi_testwrapper_create(a: *mut Allocator_t) -> Rffi_IfWrapper_t {
+pub unsafe extern "C" fn Rffi_testwrapper_create(a: *mut Allocator_t) -> RTypes_IfWrapper_t {
     let w = crate::interface::rustiface_test_wrapper::TestWrapper::default();
-    Rffi_IfWrapper_t {
+    RTypes_IfWrapper_t {
         external: cif::wrap(a, w.ext),
         internal: cif::wrap(a, w.int),
     }
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn Rffi_android_create(a: *mut Allocator_t) -> Rffi_IfWrapper_t {
+pub unsafe extern "C" fn Rffi_android_create(a: *mut Allocator_t) -> RTypes_IfWrapper_t {
     let w = crate::interface::tuntap::android::AndroidWrapper::default();
-    Rffi_IfWrapper_t {
+    RTypes_IfWrapper_t {
         external: cif::wrap(a, w.ext),
         internal: cif::wrap(a, w.int),
     }
@@ -42,10 +36,7 @@ pub struct Rffi_CryptoAuth2_t(Arc<crypto_auth::CryptoAuth>);
 pub struct Rffi_CryptoAuth2_Session_t(crypto_auth::Session);
 
 unsafe fn cu8(s: *const u8, len: usize) -> Vec<u8> {
-    let x = std::slice::from_raw_parts::<u8>(s, len);
-    let mut out = Vec::with_capacity(x.len());
-    out.copy_from_slice(x);
-    out
+    std::slice::from_raw_parts::<u8>(s, len).to_vec()
 }
 
 unsafe fn cstr(s: *const String_t) -> Option<Vec<u8>> {
@@ -56,6 +47,13 @@ unsafe fn cstr(s: *const String_t) -> Option<Vec<u8>> {
     }
 }
 
+unsafe fn strc(alloc: *mut Allocator_t, mut s: Vec<u8>) -> *mut String_t {
+    let len = s.len();
+    let bytes = s.as_mut_ptr() as *mut i8;
+    allocator::adopt(alloc, s);
+    allocator::adopt(alloc, String_t { len, bytes })
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_addUser_ipv6(
     password: *mut String_t,
@@ -82,28 +80,26 @@ pub unsafe extern "C" fn Rffi_CryptoAuth2_addUser_ipv6(
 }
 
 #[no_mangle]
-pub unsafe fn Rffi_CryptoAuth2_removeUsers(
+pub unsafe extern "C" fn Rffi_CryptoAuth2_removeUsers(
     context: *mut Rffi_CryptoAuth2_t,
     user: *mut String_t,
 ) -> c_int {
     (*context).0.remove_users(cstr(user)) as c_int
 }
 
-#[repr(C)]
-pub struct Rffi_StrList_t {
-    len: usize,
-    items: *mut String_t,
-}
-
-// TODO(cjd): we can't return a Vec<Vec<u8>> to C because it becomes opaque
-// needs fixin'
 #[no_mangle]
 pub unsafe extern "C" fn Rffi_CryptoAuth2_getUsers(
     ca: *const Rffi_CryptoAuth2_t,
     alloc: *mut Allocator_t,
-) -> *mut Vec<Vec<u8>> {
-    let users = (*ca).0.get_users();
-    allocator::adopt(alloc, (*ca).0.get_users())
+) -> *mut RTypes_StrList_t {
+    let mut users = (*ca).0.get_users();
+    let mut str_users = users.drain(..).map(|u| strc(alloc, u)).collect::<Vec<_>>();
+    let out = RTypes_StrList_t {
+        len: str_users.len(),
+        items: str_users.as_mut_ptr(),
+    };
+    allocator::adopt(alloc, str_users);
+    allocator::adopt(alloc, out)
 }
 
 #[no_mangle]
@@ -132,6 +128,7 @@ pub unsafe extern "C" fn Rffi_CryptoAuth2_newSession(
     herPublicKey: *const u8,
     requireAuth: bool,
     name: *mut c_char,
+    useNoise: bool,
 ) -> *mut Rffi_CryptoAuth2_Session_t {
     allocator::adopt(
         alloc,
@@ -151,6 +148,7 @@ pub unsafe extern "C" fn Rffi_CryptoAuth2_newSession(
                     Err(_) => None,
                 }
             },
+            useNoise,
         )),
     )
 }
@@ -199,15 +197,57 @@ pub unsafe extern "C" fn Rffi_CryptoAuth2_reset(caSession: *mut Rffi_CryptoAuth2
 }
 
 #[no_mangle]
-unsafe extern "C" fn Rffi_CryptoAuth2_getState(
+pub unsafe extern "C" fn Rffi_CryptoAuth2_getState(
     session: *mut Rffi_CryptoAuth2_Session_t,
-) -> cffi::CryptoAuth_State {
-    match (*session).0.get_state() {
-        crypto_auth::State::Init => ffist::CryptoAuth_State_INIT,
-        crypto_auth::State::SentHello => ffist::CryptoAuth_State_SENT_HELLO,
-        crypto_auth::State::ReceivedHello => ffist::CryptoAuth_State_RECEIVED_HELLO,
-        crypto_auth::State::SentKey => ffist::CryptoAuth_State_SENT_KEY,
-        crypto_auth::State::ReceivedKey => ffist::CryptoAuth_State_RECEIVED_KEY,
-        crypto_auth::State::Established => ffist::CryptoAuth_State_ESTABLISHED,
+) -> RTypes_CryptoAuth_State_t {
+    (*session).0.get_state()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Rffi_CryptoAuth2_getHerPubKey(
+    session: *const Rffi_CryptoAuth2_Session_t,
+    pkOut: *mut u8,
+) {
+    let p = (*session).0.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,
+    ipOut: *mut u8,
+) {
+    let p = (*session).0.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,
+    alloc: *mut Allocator_t,
+) -> *mut String_t {
+    match (*session).0.get_name() {
+        None => 0 as *mut String_t,
+        Some(n) => strc(alloc, n.into_bytes()),
     }
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn Rffi_CryptoAuth2_getPubKey(ca: *mut Rffi_CryptoAuth2_t, pkOut: *mut u8) {
+    let p = (*ca).0.public_key.0;
+    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,
+    statsOut: *mut RTypes_CryptoStats_t,
+) {
+    let st = (*session).0.stats();
+    (*statsOut) = st;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Rffi_panic(msg: *const c_char) -> ! {
+    panic!("{}", std::ffi::CStr::from_ptr(msg).to_string_lossy())
+}

+ 64 - 0
rust/cjdns_sys/src/rtypes.rs

@@ -0,0 +1,64 @@
+#![allow(non_snake_case)]
+#![allow(non_camel_case_types)]
+use crate::cffi::{Iface_t, String_t};
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct RTypes_IfWrapper_t {
+    pub internal: *mut Iface_t,
+    pub external: *mut Iface_t,
+}
+
+#[repr(C)]
+pub struct RTypes_StrList_t {
+    pub len: usize,
+    pub items: *mut *mut String_t,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum RTypes_CryptoAuth_State_t {
+    /// New CryptoAuth session, has not sent or received anything
+    Init = 0,
+
+    /// Sent a hello message, waiting for reply
+    SentHello = 1,
+
+    /// Received a hello message, have not yet sent a reply
+    ReceivedHello = 2,
+
+    /// Received a hello message, sent a key message, waiting for the session to complete
+    SentKey = 3,
+
+    /// Sent a hello message, received a key message, may or may not have sent some data traffic
+    /// but no data traffic has yet been received
+    ReceivedKey = 4,
+
+    /// Received data traffic, session is in run state
+    Established = 100,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub struct RTypes_CryptoStats_t {
+    /// Number of packets which were lost
+    pub lost_packets: u64,
+
+    /// Number of packets which were received but could not be validated
+    pub received_unexpected: u64,
+
+    /// Number of packets which were received (since last session setup)
+    pub received_packets: u64,
+
+    /// Number of packets which were received that were duplicates
+    pub duplicate_packets: u64,
+}
+
+#[allow(dead_code)]
+#[repr(C)]
+pub struct RTypes_ExportMe {
+    a: RTypes_IfWrapper_t,
+    b: RTypes_StrList_t,
+    c: RTypes_CryptoAuth_State_t,
+    d: RTypes_CryptoStats_t,
+}

+ 7 - 3
util/Assert.c

@@ -15,6 +15,10 @@
 #include "util/Assert.h"
 #include "util/Gcc.h"
 
+// We can't pull in Allocator or else we make a link dependency loop
+//#include "rust/cjdns_sys/Rffi.h"
+extern void Rffi_panic(const char* msg); // CHECKFILES_IGNORE
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -25,10 +29,10 @@ void Assert_failure(const char* format, ...)
     printf("\n\n");
     fflush(stdout);
     fflush(stderr);
+    char buf[1024] = {0};
     va_list args;
     va_start(args, format);
-    vfprintf(stderr, format, args);
-    fflush(stderr);
-    abort();
+    vsnprintf(buf, 1023, format, args);
     va_end(args);
+    Rffi_panic(buf);
 }