Browse Source

Merge branch 'master' into master

Caleb James DeLisle 1 year ago
parent
commit
74b0730e0b
100 changed files with 2734 additions and 903 deletions
  1. 38 0
      CHANGELOG.md
  2. 685 108
      Cargo.lock
  3. 7 16
      Cargo.toml
  4. 4 4
      README.md
  5. 1 0
      README_DE.md
  6. 3 1
      README_ES.md
  7. 2 1
      README_FR.md
  8. 105 1
      README_GR.md
  9. 5 1
      README_HR.md
  10. 4 4
      README_PT-BR.md
  11. 6 2
      README_RU.md
  12. 4 1
      README_SV.md
  13. 3 2
      README_ZHT.md
  14. 27 27
      admin/Admin.c
  15. 1 1
      admin/AdminLog.c
  16. 9 9
      admin/AuthorizedPasswords.c
  17. 2 2
      admin/AuthorizedPasswords.h
  18. 4 2
      admin/angel/Core.c
  19. 2 2
      admin/angel/InterfaceWaiter.c
  20. 23 17
      android_do
  21. 4 2
      benc/Object.h
  22. 9 9
      benc/serialization/json/JsonBencMessageReader.c
  23. 2 2
      benc/serialization/standard/BencMessageReader.c
  24. 4 4
      benc/serialization/standard/BencMessageWriter.c
  25. 15 13
      client/AdminClient.c
  26. 13 17
      client/cjdroute2.c
  27. 1 0
      contrib/c/mkpasswd.c
  28. 1 1
      contrib/c/privatetopublic.c
  29. 1 0
      contrib/c/sybilsim.c
  30. 1 1
      contrib/simple-install/README.md
  31. 1 0
      contrib/simple-install/cjdns-installer.sh
  32. 186 0
      crypto/Ca.h
  33. 169 68
      crypto/CryptoAuth.c
  34. 32 48
      crypto/CryptoAuth.h
  35. 25 2
      crypto/CryptoAuth_pvt.h
  36. 10 10
      crypto/Sign.c
  37. 2 2
      crypto/Sign_admin.c
  38. 28 3
      crypto/random/Random.c
  39. 3 3
      crypto/random/Random.h
  40. 3 3
      crypto/random/seed/BsdKernArndSysctlRandomSeed.c
  41. 1 1
      crypto/random/seed/BsdKernArndSysctlRandomSeed.h
  42. 3 3
      crypto/random/seed/DevUrandomRandomSeed.c
  43. 1 1
      crypto/random/seed/DevUrandomRandomSeed.h
  44. 3 3
      crypto/random/seed/GetEntropyRandomSeed.c
  45. 1 1
      crypto/random/seed/GetEntropyRandomSeed.h
  46. 3 3
      crypto/random/seed/LinuxRandomUuidSysctlRandomSeed.c
  47. 1 1
      crypto/random/seed/LinuxRandomUuidSysctlRandomSeed.h
  48. 3 3
      crypto/random/seed/ProcSysKernelRandomUuidRandomSeed.c
  49. 1 1
      crypto/random/seed/ProcSysKernelRandomUuidRandomSeed.h
  50. 7 7
      crypto/random/seed/RandomSeed.c
  51. 6 6
      crypto/random/seed/RandomSeed.h
  52. 3 3
      crypto/random/seed/RtlGenRandomSeed.c
  53. 1 1
      crypto/random/seed/RtlGenRandomSeed.h
  54. 1 1
      crypto/random/seed/SystemRandomSeed.c
  55. 1 1
      crypto/random/seed/SystemRandomSeed.h
  56. 3 3
      crypto/random/test/DeterminentRandomSeed.c
  57. 1 1
      crypto/random/test/DeterminentRandomSeed.h
  58. 1 1
      crypto/random/test/Random_test.c
  59. 102 43
      crypto/test/CryptoAuthFuzz.c
  60. 28 0
      crypto/test/CryptoAuthFuzz.h
  61. 26 0
      crypto/test/CryptoAuthFuzz_noise_fuzz_test.c
  62. 0 0
      crypto/test/CryptoAuthFuzz_noise_fuzz_test_cases/Default.hex
  63. 26 0
      crypto/test/CryptoAuthFuzz_old_fuzz_test.c
  64. 4 0
      crypto/test/CryptoAuthFuzz_old_fuzz_test_cases/Default.hex
  65. 26 0
      crypto/test/CryptoAuthFuzz_oldnew_fuzz_test.c
  66. 4 0
      crypto/test/CryptoAuthFuzz_oldnew_fuzz_test_cases/Default.hex
  67. 57 0
      crypto/test/CryptoAuth_randnonce_test.c
  68. 185 99
      crypto/test/CryptoAuth_test.c
  69. 81 80
      crypto/test/CryptoAuth_unit_test.c
  70. 358 0
      crypto/test/TestCa.c
  71. 79 0
      crypto/test/TestCa.h
  72. 41 35
      dht/Pathfinder.c
  73. 1 1
      dht/ReplyModule.c
  74. 5 5
      dht/SerializationModule.c
  75. 5 5
      dht/dhtcore/Janitor.c
  76. 6 6
      dht/dhtcore/NodeStore.c
  77. 1 1
      dht/dhtcore/RouterModule.c
  78. 2 8
      do
  79. 4 4
      doc/Whitepaper.md
  80. 1 3
      exception/Er.c
  81. 4 4
      interface/ASynchronizer.c
  82. 6 2
      interface/ETHInterface_admin.c
  83. 14 14
      interface/ETHInterface_darwin.c
  84. 15 16
      interface/ETHInterface_linux.c
  85. 32 34
      interface/FramingIface.c
  86. 12 2
      interface/Iface.c
  87. 19 9
      interface/Iface.h
  88. 33 36
      interface/UDPInterface.c
  89. 6 2
      interface/UDPInterface_admin.c
  90. 1 1
      interface/addressable/AddrIface.h
  91. 6 5
      interface/addressable/AddrIfaceMuxer.c
  92. 10 10
      interface/addressable/PacketHeaderToUDPAddrIface.c
  93. 12 12
      interface/test/FramingIface_fuzz_test.c
  94. 2 2
      interface/test/RustIface_test.c
  95. 3 3
      interface/tuntap/ARPServer.c
  96. 6 6
      interface/tuntap/AndroidWrapper.c
  97. 9 9
      interface/tuntap/BSDMessageTypeWrapper.c
  98. 8 8
      interface/tuntap/NDPServer.c
  99. 4 4
      interface/tuntap/SocketWrapper.c
  100. 4 4
      interface/tuntap/TAPWrapper.c

+ 38 - 0
CHANGELOG.md

@@ -0,0 +1,38 @@
+# Cjdns Changelog
+
+## Version 22 - Noisemaker
+February 3, 2023
+
+It's been since September 18, 2020 when cjdns v21 was tagged out, and brought only small experimental inclusion of
+Rust code to cjdns. v22 makes Rust a main language in which cjdns is written, and it is foreseen that in v23, almost
+all interactions with the OS will be done in Rust.
+
+### Major Changes
+1. New protocol version v22, compatibility is maintained with v21 and v20 (no change in compatibility)
+  * This new protocol version brings a new CryptoAuth protocol based on the NOISE protocol used by WireGuard® VPN.
+  The NOISE protocol is used in all direct peering connections where both sides are v22.
+  * The legacy CryptoAuth protocol remains but has been entirely re-written in Rust,
+  the C version remains only for testing purposes.
+2. RPC `InterfaceController_peerStats()` Now contains Integer noiseProto: 1 if using the NOISE protocol for communication
+3. RPC `InterfaceController_disconnectPeer()` Now disconnects ALL sessions to given peer address instead of only the first
+4. RPC `InterfaceController_timestampPackets()` has been removed, as it only affected debug logging and was rarely used
+5. Libuv code is now compiled using the cjdns build system, it is nolonger compiled using gyp so **python is nolonger needed to build cjdns**
+6. Removed `cjdroute --bench` which was not an accurate measure of expected performance
+
+### Minor Changes
+1. Made fields of Message structure so they will be accessed through accessors - first step to move Message into Rust
+2. Make cjdns Error return value use a Rust anyhow error
+3. In preparation for removal of Libuv, we have replaced the following Libuv functions with Rust implementations:
+  * IP Address manipulation functions: `uv_inet_pton` / `uv_inet_pton`
+  * Current time: `uv_now` / `uv_hrtime`
+  * Child process: `uv_spawn` / `uv_exepath` / `uv_process_kill`
+4. We nolonger put `makekeys`, `mkpasswd`, `privatetopublic`, `publictoip6`, `randombytes`, and `sybilsim` in the main folder
+  * In the future: `makekeys`, `privatetopublic`, `publictoip6`, and `randombytes` will be built as a separate optional component
+  * `mkpasswd` will be dropped because it is too trivial to be worth maintaining
+  * `sybilsim` will be dropped because it is nolonger maintained
+5. Removed from SwitchCore.c the possibility of an interface to be "down" which never exists in reality
+6. New logger for Rust code which uses the cjdns logger as a backend
+7. CryptoAuth is now an (asynchronous) Iface rather than a function you call to encrypt and decrypt
+
+# Older versions
+For earlier versions, see ./util/version/Version.h

File diff suppressed because it is too large
+ 685 - 108
Cargo.lock


+ 7 - 16
Cargo.toml

@@ -1,19 +1,10 @@
 [workspace]
-
-members = [
-    "rust/cjdns_sys",
-    "rust/cjdroute",
-    "rust/publictoip6",
-    "rust/mkpasswd",
-    "rust/sybilsim",
-    "rust/testcjdroute",
-    "rust/randombytes",
-    "rust/privatetopublic",
-    "rust/makekeys",
-]
+members = ["rust/cjdns_sys"]
 
 [profile.release]
-lto = true
-opt-level = "z"
-codegen-units = 1
-panic = "abort"
+opt-level = 2
+panic = "unwind"
+
+# In debug mode, enable optimizations for dependencies, but not for our code
+[profile.dev.package."*"]
+opt-level = 2

+ 4 - 4
README.md

@@ -53,7 +53,7 @@ scalability issues that plague existing networks.
 
 ## Community
 
-* [irc://irc.freenode.org/#cjdns][IRC Web]
+* [irc://irc.efnet.org/#cjdns][IRC Web]
 * [Hyperboria][] the largest cjdns network, as of October 2015 there are 2100 nodes.
 * [/r/darknetplan][]
 * [#cjdns on Twitter][]
@@ -143,7 +143,7 @@ If you need to build from source, everything you need can be installed like this
     pacman -S nodejs git base-devel
 
 Alternatively, you may like to install via AUR from the package, `cjdns-git`.
-After Installation, The configuration file is located at `/etc/cjdroute.conf`.
+After installation, the configuration file is located at `/etc/cjdroute.conf`.
 To start the service `cjdns.service`, do:
 
     systemctl start cjdns
@@ -230,14 +230,14 @@ Then Follow the steps below:
 
 *Sorry for so many steps. A package is being worked on currently*
 
-##### 1. Retrieve cjdns from GitHub
+### 1. Retrieve cjdns from GitHub
 
 Clone the repository from GitHub and change to the source directory:
 
     git clone https://github.com/cjdelisle/cjdns.git cjdns
     cd cjdns
 
-##### 2. Build
+### 2. Build
 
     ./do
 

+ 1 - 0
README_DE.md

@@ -9,6 +9,7 @@
 [简体中文](README_ZHCN.md)
 [Español](README_ES.md)
 [Français](README_FR.md)
+[Português brasileiro](README_PT-BR.md)
 
 #### *Netzwerk neu erfunden*
 

+ 3 - 1
README_ES.md

@@ -1,5 +1,6 @@
 # cjdns
 
+[English](README.md)
 [Русская версия](README_RU.md)
 [Hrvatski](README_HR.md)
 [Svenska](README_SV.md)
@@ -9,6 +10,7 @@
 [简体中文](README_ZHCN.md)
 [Español](README_ES.md)
 [Français](README_FR.md)
+[Português brasileiro](README_PT-BR.md)
 
 #### *Reinventando las redes*
 
@@ -17,7 +19,7 @@ la asignación de direcciones y una tabla distribuida de hashes para el
 ruteo. Esto provee redes de casi-nula-configuración, y previene mucho de los
 problemas de seguridad y escalabilidad que plagan a las redes existentes.
 
-[![Build Status](https://travis-ci.org/cjdelisle/cjdns.svg?branch=master)](https://travis-ci.org/cjdelisle/cjdns)
+[![Build Status](https://api.travis-ci.org/cjdelisle/cjdns.svg?branch=master)](https://travis-ci.org/cjdelisle/cjdns)
 [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/387/badge)](https://bestpractices.coreinfrastructure.org/projects/387)
 [![tip for next commit](https://tip4commit.com/projects/941.svg)](https://tip4commit.com/github/cjdelisle/cjdns)
 [![irc](https://img.shields.io/badge/irc%20chat-%23cjdns-blue.svg)](https://kiwiirc.com/client/irc.efnet.org/?nick=visitor|?#cjdns)

+ 2 - 1
README_FR.md

@@ -2,6 +2,7 @@ Traduction à partir de la version
 [`cjdns-v19.1`](https://github.com/woshilapin/cjdns/blob/cjdns-v19.1/README.md)
 # cjdns
 
+[English](README.md)
 [Русская версия](README_RU.md)
 [Hrvatski](README_HR.md)
 [Svenska](README_SV.md)
@@ -10,7 +11,7 @@ Traduction à partir de la version
 [繁體中文](README_ZHT.md)
 [简体中文](README_ZHCN.md)
 [Español](README_ES.md)
-[Français](README_FR.md)
+[Português brasileiro](README_PT-BR.md)
 
 #### *Le réseau réinventé*
 

+ 105 - 1
README_GR.md

@@ -9,6 +9,7 @@
 [简体中文](README_ZHCN.md)
 [Español](README_ES.md)
 [Français](README_FR.md)
+[Português brasileiro](README_PT-BR.md)
 
 #### *Η δικτύωση επανεφευρέθηκε*
 
@@ -18,8 +19,10 @@ Cjdns υλοποιεί ένα κρυπτογραφημένο δίκτυο IPV6 
 επεκτασιμότητας που μαστίζουν τα υπάρχοντα δίκτυα.
 
 [![Build Status](https://api.travis-ci.org/cjdelisle/cjdns.svg?branch=master)](https://travis-ci.org/cjdelisle/cjdns)
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/387/badge)](https://bestpractices.coreinfrastructure.org/projects/387)
 [![tip for next commit](https://tip4commit.com/projects/941.svg)](https://tip4commit.com/github/cjdelisle/cjdns)
 [![irc](https://img.shields.io/badge/irc%20chat-%23cjdns-blue.svg)](https://kiwiirc.com/client/irc.efnet.org/?nick=visitor|?#cjdns)
+![License](https://img.shields.io/github/license/cjdelisle/cjdns.svg)
 
 ## Γνώμες πελατών
 
@@ -128,11 +131,99 @@ Cjdns υλοποιεί ένα κρυπτογραφημένο δίκτυο IPV6 
 
     pacman -S nodejs git base-devel
 
+Εναλλακτικά, μπορείτε να το εγκαταστήσετε μέσω του AUR από το πακέτο, `cjdns-git`.
+Μετά την εγκατάσταση, το αρχείο ρυθμίσεων βρίσκεται στην τοποθεσία `/etc/cjdroute.conf`.
+Για να ξεκινήσετε το service `cjdns.service`, κάντε:
+
+    systemctl start cjdns
+
+Για να το σταματήσετε:
+
+    systemctl stop cjdns
+
+#### Gentoo:
+
+Το cjdns δεν βρίσκεται ακόμα στο κύριο εναποθετήριο του Gentoo, οπότε θα χρειαστεί να χρησιμοποιήσετε το ένα overlay.
+Ο ευκολότερος τρόπος είναι να χρησιμοποιήσετε το Layman αλλά μπορείτε και χειροκίνητα επίσης.
+
+##### Layman:
+
+Πρώτα, θα χρειαστεί να εγκαταστήσετε το layman.
+
+    emerge layman
+
+Αν το layman εγκαταστάθηκε σωστά, μπορείτε να προσθέσετε το overlay
+
+    layman -f
+    layman -a weuxel
+
+Για μελλοντικές αναβαθμίσεις του overlay χρησιμοποιήστε
+
+    layman -S
+
+Τώρα μπορείτε να εγκαταστήσετε το cjdns
+
+    emerge cjdns
+
+##### Χειροκίνητα:
+
+Κλωνοποιήστε το εναποθετήριο του overlay
+
+    cd /opt
+    git clone https://github.com/Weuxel/portage-weuxel.git
+
+Πείτε στο portage να χρησιμοποιήσει το εναποθετήριο
+
+    cd /etc/portage/repos.conf/
+
+Δημιουργήστε ένα αρχείο με όνομα `portage-weuxel.conf` που να περιέχει
+
+    [weuxel]
+    location = /opt/portage-weuxel
+    masters = gentoo
+    auto-sync = yes
+
+Τώρα συγχρονίστε
+
+    emerge --sync
+
+Και εγκαταστήστε το cjdns
+
+    emerge cjdns
+
+#### Αυτόματος έλεγχος διακοπής λειτουργίας και επανεκκίνηση
+
+Αντιγράψτε το openrc init script από `contrib/openrc` στο φάκελο `/etc/init.d/` και αλλάξτε τις παραμέτρους `CONFFILE` και `command` σύμφωνα με τις ανάγκες σας.
+Μετά ξεκινήστε το cjdns πληκτρολογώντας
+
+    /etc/init.d/cjdns start
+
+Ρυθμίστε το init system ώστε να ξεκινά το cjdns αυτόματα
+
+    rc-update add cjdns default
+
+Αντιγράψτε το service_restart script `contrib/gentoo/service_restart.sh` σε οποιονδήποτε φάκελο πιστεύτε πως θα έπρεπε να βρίσκεται στο
+σύστημά σας και αλλάξτε τη διεύθυνση eMail. Αν δε θέλετε να ειδοποιήστε, μαρκάρετε τη γραμμή ως σχόλιο.
+Τώρα προσθέστε μια εγγραφή στο crontab με αυτό τον τρόπο
+
+    # Restart crashed Services
+    * * * * *       root    /path/to/script/service_restart.sh
+
+#### Solus:
+
+Εξαρτήσεις:
+
+    sudo eopkg install nodejs git build-essential system.devel python gcc binutils kernal-headers xorg-server-devel
+
+Ακολουθήστε τα βήματα παρακάτω:
+
+*Ζητούμε συγγνώμη για τα τόσα πολλά βήματα. Προετοιμάζεται ένα πακέτο*
+
 ### 1. Ανακτήστε το cjdns από το GitHub
 
 Κλωνοποίηστε το αποθετήριο από το GitHub και περάστε στο πηγαίο φάκελο:
 
-    git clone https://github.com/cjdelisle/cjdns.git
+    git clone https://github.com/cjdelisle/cjdns.git cjdns
     cd cjdns
 
 ### 2. Χτίστε
@@ -374,6 +465,19 @@ TUN/TAP συσκευή - αυτό είναι στάνταρ πρωτόκολλο
 * την **Python library**; δείτε [εδώ](contrib/python/README.md).
 * την **Perl library**, συντηρείται από τον Mikey; δείτε [εδώ](contrib/perl/CJDNS/README).
 
+## Αναφορά προβλημάτων
+1. Μην αναφέρετε σε αυτό το εναποθετήριο, αντ' αυτού παρακαλούμε αναφέρετέ το στο https://github.com/hyperboria/bugs/issues
+2. Μπείτε στο IRC και μιλήστε με κάποιο
+3. Το τι μπορεί να συμβεί είναι είτε
+ * κάποιος μπορεί να το φτιάξει
+ * εσείς μπορείτε να το φτιάξετε
+ * κανείς δεν ασχολείτε και παραμένει ξεχασμένο μέχρι κάποιος να πέσει πάνω του αργότερα και το φτιάξει ή απλά θα χαθεί σε κάποιο ανασχεδιασμό
+ * κανείς δε μπορεί να το φτιάξει εκείνη τη στιγμή αλλά είναι σημαντικό να το θυμόμαστε γιατί έχει μεγάλη σημασία στον τρόπο που δημιουργείται ο κώδικας, σε αυτή την περίπτωση χρειάζεται να εξηγηθεί με τεχνικούς όρους από κάποιον που είναι οικείος με τον κώδικα. Μπορούν να κάνουν κάποιο pull request στο φάκελο docs/bugs.
+
+### Ασφάλεια
+Τα προβλήματα ασφαλείας θα πρέπει να αναφέρονται στο IRC όπως και τα υπόλοιπα bugs. Δεν έχουμε κάποιο κλειστό group ανθρώπων με εξειδικευμένη γνώση οπότε αυτό σημαίνει πως η προεπιλεγμένη μέθοδος αναφοράς προβλημάτων ασφαλείας είναι η πλήρης περιγραφή.
+
+Δείτε: [security_specification.md](https://github.com/cjdelisle/cjdns/blob/master/doc/security_specification.md) ώστε να καταλάβετε αν ένα πιθανό πρόβλημα ασφάλεια είναι πραγματικά πρόβλημα ασφάλειας.
 
 [IRC Web]: http://chat.efnet.org/irc.cgi?chan=%23cjdns
 [Hyperboria]: https://hyperboria.net

+ 5 - 1
README_HR.md

@@ -9,6 +9,7 @@
 [简体中文](README_ZHCN.md)
 [Español](README_ES.md)
 [Français](README_FR.md)
+[Português brasileiro](README_PT-BR.md)
 
 #### *Umrežavanje iznova*
 
@@ -18,7 +19,10 @@ mrežnu konfiguraciju i sprječava mnoge sigurnosne i
 skalabilne probleme koje muče trenutne mreže.
 
 [![Build Status](https://api.travis-ci.org/cjdelisle/cjdns.svg?branch=master)](https://travis-ci.org/cjdelisle/cjdns)
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/387/badge)](https://bestpractices.coreinfrastructure.org/projects/387)
 [![napojnica za sljedeću promjenu](https://tip4commit.com/projects/941.svg)](https://tip4commit.com/github/cjdelisle/cjdns)
+[![irc](https://img.shields.io/badge/irc%20chat-%23cjdns-blue.svg)](https://kiwiirc.com/client/irc.efnet.org/?nick=visitor|?#cjdns)
+![License](https://img.shields.io/github/license/cjdelisle/cjdns.svg)
 
 ## Iskustva
 
@@ -39,7 +43,7 @@ skalabilne probleme koje muče trenutne mreže.
 
 ## Zajednica
 
-* irc://irc.efnet.org/#cjdns ([web client][IRC Web])
+* [irc://irc.efnet.org/#cjdns][IRC Web]
 * [Hyperboria][]
 * [Projekt Meshnet][]
 * [/r/darknetplan][]

+ 4 - 4
README_PT-BR.md

@@ -1,5 +1,6 @@
 # cjdns
 
+[English](README.md)
 [Русская версия](README_RU.md)
 [Hrvatski](README_HR.md)
 [Svenska](README_SV.md)
@@ -9,13 +10,12 @@
 [简体中文](README_ZHCN.md)
 [Español](README_ES.md)
 [Français](README_FR.md)
-[Português brasileiro](README_PT-BR.md)
 
-#### *Rede Reinventada*
+#### *Networking Reinventada*
 
 O Cjdns implementa uma rede IPv6 criptografada usando criptografia de chave pública para
 alocação de endereços e uma tabela de hash distribuída para roteamento. Isso fornece
-rede de configuração quase zero e evita muitos dos aspectos de segurança e
+configuração de rede quase zero e evita muitos dos aspectos de segurança e
 problemas de escalabilidade que afetam as redes existentes.
 
 [![Build Status](https://api.travis-ci.org/cjdelisle/cjdns.svg?branch=master)](https://travis-ci.org/cjdelisle/cjdns)
@@ -64,7 +64,7 @@ problemas de escalabilidade que afetam as redes existentes.
 
 * [Objetivos do projeto](doc/projectGoals.md)
 * [Cjdns Whitepaper](doc/Whitepaper.md)
-* [Cjdns na Wikipedia][]
+* [Cjdns na Wikipedia](https://fr.wikipedia.org/wiki/Cjdns)
 
 Configuração avançada:
 

+ 6 - 2
README_RU.md

@@ -9,13 +9,17 @@
 [简体中文](README_ZHCN.md)
 [Español](README_ES.md)
 [Français](README_FR.md)
+[Português brasileiro](README_PT-BR.md)
 
 Безопасная, зашифрованная сеть для обычных людей.
 
 Cjdns — это зашифрованная IPv6 сеть, в которой используются публичные ключи шифрования для присвоения публичного адреса и распределённой таблицы маршрутизации (DHT). Это позволяет создавать сети с очень простой настройкой, которые будут защищены от потенциальных проблем ныне существующих IPv4 и IPv6 сетей.
 
-[![Build Status](https://api.travis-ci.org/cjdelisle/cjdns.png?branch=master)](https://travis-ci.org/cjdelisle/cjdns)
-[![For next commit](https://tip4commit.com/projects/941.svg)](https://tip4commit.com/github/cjdelisle/cjdns)
+[![Build Status](https://api.travis-ci.org/cjdelisle/cjdns.svg?branch=master)](https://travis-ci.org/cjdelisle/cjdns)
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/387/badge)](https://bestpractices.coreinfrastructure.org/projects/387)
+[![tip for next commit](https://tip4commit.com/projects/941.svg)](https://tip4commit.com/github/cjdelisle/cjdns)
+[![irc](https://img.shields.io/badge/irc%20chat-%23cjdns-blue.svg)](https://kiwiirc.com/client/irc.efnet.org/?nick=visitor|?#cjdns)
+![License](https://img.shields.io/github/license/cjdelisle/cjdns.svg)
 
 ## Рекомендательные письма
 

+ 4 - 1
README_SV.md

@@ -9,6 +9,7 @@
 [简体中文](README_ZHCN.md)
 [Español](README_ES.md)
 [Français](README_FR.md)
+[Português brasileiro](README_PT-BR.md)
 
 #### *Datornätverk - Ett nytt sätt*
 
@@ -18,9 +19,11 @@ hashtabell (DHT, eller Distributed Hash Table på engelska). Genom denna design
 uppnås ett nätverk som knappt kräver någon konfiguration. Vi blir också av med
 många skalnings- och säkerhetsproblem som andra nätverk har.
 
-[![Build Status](https://travis-ci.org/cjdelisle/cjdns.svg?branch=master)](https://travis-ci.org/cjdelisle/cjdns)
+[![Build Status](https://api.travis-ci.org/cjdelisle/cjdns.svg?branch=master)](https://travis-ci.org/cjdelisle/cjdns)
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/387/badge)](https://bestpractices.coreinfrastructure.org/projects/387)
 [![tip for next commit](https://tip4commit.com/projects/941.svg)](https://tip4commit.com/github/cjdelisle/cjdns)
 [![irc](https://img.shields.io/badge/irc%20chat-%23cjdns-blue.svg)](https://kiwiirc.com/client/irc.efnet.org/?nick=visitor|?#cjdns)
+![License](https://img.shields.io/github/license/cjdelisle/cjdns.svg)
 
 ## Vitsord
 

+ 3 - 2
README_ZHT.md

@@ -1,4 +1,3 @@
-
 # cjdns
 
 [English](README.md)
@@ -10,15 +9,17 @@
 [简体中文](README_ZHCN.md)
 [Español](README_ES.md)
 [Français](README_FR.md)
+[Português brasileiro](README_PT-BR.md)
 
 #### *重朔整個網路*
 
 Cjdns 利用「加密的IPv6」及「公鑰加密」來分配網路地址並利用「Distributed Hash Table」逕行路由。它能提供近似「零配置網路(Zero-Configuration Networking)」,並且能防範在現有網路中存在的很多和安全、可擴展性相關的問題。
 
-[![Build Status](https://travis-ci.org/cjdelisle/cjdns.svg?branch=master)](https://travis-ci.org/cjdelisle/cjdns)
+[![Build Status](https://api.travis-ci.org/cjdelisle/cjdns.svg?branch=master)](https://travis-ci.org/cjdelisle/cjdns)
 [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/387/badge)](https://bestpractices.coreinfrastructure.org/projects/387)
 [![tip for next commit](https://tip4commit.com/projects/941.svg)](https://tip4commit.com/github/cjdelisle/cjdns)
 [![irc](https://img.shields.io/badge/irc%20chat-%23cjdns-blue.svg)](https://kiwiirc.com/client/irc.efnet.org/?nick=visitor|?#cjdns)
+![License](https://img.shields.io/github/license/cjdelisle/cjdns.svg)
 
 ## 評價
 

+ 27 - 27
admin/Admin.c

@@ -113,7 +113,7 @@ struct Admin_pvt
     Identity
 };
 
-static struct Error_s sendMessage(
+static struct RTypes_Error_t* sendMessage(
     struct Message* message, struct Sockaddr* dest, struct Admin_pvt* admin)
 {
     // stack overflow when used with admin logger.
@@ -122,7 +122,7 @@ static struct Error_s sendMessage(
     return Iface_send(&admin->iface, message);
 }
 
-static struct Error_s sendBenc(Dict* message,
+static struct RTypes_Error_t* sendBenc(Dict* message,
                                struct Sockaddr* dest,
                                struct Allocator* alloc,
                                struct Admin_pvt* admin,
@@ -130,8 +130,8 @@ static struct Error_s sendBenc(Dict* message,
 {
     Message_reset(admin->tempSendMsg);
     Er_assert(BencMessageWriter_write(message, admin->tempSendMsg));
-    struct Message* msg = Message_new(0, admin->tempSendMsg->length + 32, alloc);
-    Er_assert(Message_epush(msg, admin->tempSendMsg->bytes, admin->tempSendMsg->length));
+    struct Message* msg = Message_new(0, Message_getLength(admin->tempSendMsg) + 32, alloc);
+    Er_assert(Message_epush(msg, admin->tempSendMsg->msgbytes, Message_getLength(admin->tempSendMsg)));
     Message_setAssociatedFd(msg, fd);
     return sendMessage(msg, dest, admin);
 }
@@ -157,7 +157,7 @@ static int checkAddress(struct Admin_pvt* admin, int index, uint64_t now)
 static void clearExpiredAddresses(void* vAdmin)
 {
     struct Admin_pvt* admin = Identity_check((struct Admin_pvt*) vAdmin);
-    uint64_t now = Time_currentTimeMilliseconds(admin->eventBase);
+    uint64_t now = Time_currentTimeMilliseconds();
     int count = 0;
     for (int i = admin->map.count - 1; i >= 0; i--) {
         if (checkAddress(admin, i, now)) {
@@ -180,7 +180,7 @@ static int sendMessage0(Dict* message, String* txid, struct Admin* adminPub, int
 
     struct Allocator* alloc = NULL;
     if (admin->currentRequest) {
-        alloc = admin->currentRequest->alloc;
+        alloc = Message_getAlloc(admin->currentRequest);
     } else {
         alloc = Allocator_child(admin->allocator);
     }
@@ -191,7 +191,7 @@ static int sendMessage0(Dict* message, String* txid, struct Admin* adminPub, int
     // out forever after a disconnection.
     if (!admin->currentRequest) {
         int index = Map_LastMessageTimeByAddr_indexForKey(&addr, &admin->map);
-        uint64_t now = Time_currentTimeMilliseconds(admin->eventBase);
+        uint64_t now = Time_currentTimeMilliseconds();
         if (index < 0 || checkAddress(admin, index, now)) {
             return Admin_sendMessage_CHANNEL_CLOSED;
         }
@@ -228,13 +228,13 @@ static inline bool authValid(Dict* message, struct Message* messageBytes, struct
         int64_t* cookieInt = Dict_getIntC(message, "cookie");
         cookie = (cookieInt) ? *cookieInt : 0;
     }
-    uint64_t nowSecs = Time_currentTimeSeconds(admin->eventBase);
+    uint64_t nowSecs = Time_currentTimeSeconds();
     String* submittedHash = Dict_getStringC(message, "hash");
     if (cookie >  nowSecs || cookie < nowSecs - 20 || !submittedHash || submittedHash->len != 64) {
         return false;
     }
 
-    uint8_t* hashPtr = CString_strstr(messageBytes->bytes, submittedHash->bytes);
+    uint8_t* hashPtr = CString_strstr(messageBytes->msgbytes, submittedHash->bytes);
 
     if (!hashPtr || !admin->password) {
         return false;
@@ -246,7 +246,7 @@ static inline bool authValid(Dict* message, struct Message* messageBytes, struct
     crypto_hash_sha256(hash, passAndCookie, CString_strlen((char*) passAndCookie));
     Hex_encode(hashPtr, 64, hash, 32);
 
-    crypto_hash_sha256(hash, messageBytes->bytes, messageBytes->length);
+    crypto_hash_sha256(hash, messageBytes->msgbytes, Message_getLength(messageBytes));
     Hex_encode(hashPtr, 64, hash, 32);
     int res = crypto_verify_32(hashPtr, submittedHash->bytes);
     res |= crypto_verify_32(hashPtr + 32, submittedHash->bytes + 32);
@@ -345,7 +345,7 @@ static void handleRequest(Dict* messageDict,
         //Log_debug(admin->logger, "Got a request for a cookie");
         Dict* d = Dict_new(allocator);
         char bytes[32];
-        snprintf(bytes, 32, "%u", (uint32_t) Time_currentTimeSeconds(admin->eventBase));
+        snprintf(bytes, 32, "%u", (uint32_t) Time_currentTimeSeconds());
         String* theCookie = &(String) { .len = CString_strlen(bytes), .bytes = bytes };
         Dict_putString(d, cookie, theCookie, allocator);
         Admin_sendMessage(d, txid, &admin->pub);
@@ -374,7 +374,7 @@ static void handleRequest(Dict* messageDict,
     // Then sent a valid authed query, lets track their address so they can receive
     // asynchronous messages.
     int index = Map_LastMessageTimeByAddr_indexForKey(&src, &admin->map);
-    uint64_t now = Time_currentTimeMilliseconds(admin->eventBase);
+    uint64_t now = Time_currentTimeMilliseconds();
     admin->asyncEnabled = 1;
     if (index >= 0) {
         admin->map.values[index]->timeOfLastMessage = now;
@@ -395,8 +395,8 @@ static void handleRequest(Dict* messageDict,
         if (String_equals(query, admin->functions[i].name)
             && (authed || !admin->functions[i].needsAuth))
         {
-            if (checkArgs(args, &admin->functions[i], txid, message->alloc, admin)) {
-                admin->functions[i].call(args, admin->functions[i].context, txid, message->alloc);
+            if (checkArgs(args, &admin->functions[i], txid, Message_getAlloc(message), admin)) {
+                admin->functions[i].call(args, admin->functions[i].context, txid, Message_getAlloc(message));
             }
             noFunctionsCalled = false;
         }
@@ -421,39 +421,39 @@ static void handleMessage(struct Message* message,
                           struct Admin_pvt* admin)
 {
     if (Defined(Log_KEYS)) {
-        uint8_t lastChar = message->bytes[message->length - 1];
-        message->bytes[message->length - 1] = '\0';
+        uint8_t lastChar = message->msgbytes[Message_getLength(message) - 1];
+        message->msgbytes[Message_getLength(message) - 1] = '\0';
         Log_keys(admin->logger, "Got message from [%s] [%s]",
-                 Sockaddr_print(src, alloc), message->bytes);
-        message->bytes[message->length - 1] = lastChar;
+                 Sockaddr_print(src, alloc), message->msgbytes);
+        message->msgbytes[Message_getLength(message) - 1] = lastChar;
     }
 
     // handle non empty message data
-    if (message->length > Admin_MAX_REQUEST_SIZE) {
+    if (Message_getLength(message) > Admin_MAX_REQUEST_SIZE) {
         #define TOO_BIG "d5:error16:Request too big.e"
         #define TOO_BIG_STRLEN (sizeof(TOO_BIG) - 1)
-        Bits_memcpy(message->bytes, TOO_BIG, TOO_BIG_STRLEN);
-        message->length = TOO_BIG_STRLEN;
+        Bits_memcpy(message->msgbytes, TOO_BIG, TOO_BIG_STRLEN);
+        Er_assert(Message_truncate(message, TOO_BIG_STRLEN));
         sendMessage(message, src, admin);
         return;
     }
 
-    int origMessageLen = message->length;
+    int origMessageLen = Message_getLength(message);
     Dict* messageDict = NULL;
     const char* err = BencMessageReader_readNoExcept(message, alloc, &messageDict);
     if (err) {
         Log_warn(admin->logger,
                  "Unparsable data from [%s] content: [%s] error: [%s]",
                  Sockaddr_print(src, alloc),
-                 Hex_print(message->bytes, message->length, alloc),
+                 Hex_print(message->msgbytes, Message_getLength(message), alloc),
                  err);
         return;
     }
 
-    if (message->length) {
+    if (Message_getLength(message)) {
         Log_warn(admin->logger,
                  "Message from [%s] contained garbage after byte [%d] content: [%s]",
-                 Sockaddr_print(src, alloc), message->length, message->bytes);
+                 Sockaddr_print(src, alloc), Message_getLength(message), message->msgbytes);
         return;
     }
 
@@ -476,7 +476,7 @@ static Iface_DEFUN receiveMessage(struct Message* message, struct Iface* iface)
     Allocator_free(alloc);
     // We don't return errors here because the caller can't make use of them
     // instead we reply with anything which went wrong.
-    return Error(NONE);
+    return NULL;
 }
 
 void Admin_registerFunctionWithArgCount(char* name,
@@ -527,7 +527,7 @@ void Admin_registerFunctionWithArgCount(char* name,
 static void importFd(Dict* args, void* vAdmin, String* txid, struct Allocator* requestAlloc)
 {
     struct Admin_pvt* admin = Identity_check((struct Admin_pvt*) vAdmin);
-    int fd = admin->currentRequest->associatedFd;
+    int fd = Message_getAssociatedFd(admin->currentRequest);
     Dict* res = Dict_new(requestAlloc);
     char* error = "none";
     if (fd < 0) {

+ 1 - 1
admin/AdminLog.c

@@ -123,7 +123,7 @@ static Dict* makeLogMessage(struct Subscription* subscription,
                             String* message,
                             struct Allocator* alloc)
 {
-    int64_t now = (int64_t) Time_currentTimeSeconds(logger->base);
+    int64_t now = (int64_t) Time_currentTimeSeconds();
 
     Dict* out = Dict_new(alloc);
 

+ 9 - 9
admin/AuthorizedPasswords.c

@@ -21,7 +21,7 @@
 struct Context
 {
     struct Admin* admin;
-    struct CryptoAuth* ca;
+    Ca_t* ca;
     struct Allocator* allocator;
     Identity
 };
@@ -52,13 +52,13 @@ static void add(Dict* args, void* vcontext, String* txid, struct Allocator* allo
         ipv6Arg = ipv6Bytes;
     }
 
-    int32_t ret = CryptoAuth_addUser_ipv6(passwd, user, ipv6Arg, context->ca);
+    int32_t ret = Ca_addUser_ipv6(passwd, user, ipv6Arg, context->ca);
 
     switch (ret) {
         case 0:
             sendResponse(String_CONST("none"), context->admin, txid, alloc);
             break;
-        case CryptoAuth_addUser_DUPLICATE:
+        case Ca_addUser_DUPLICATE:
             sendResponse(String_CONST("Password already added."), context->admin, txid, alloc);
             break;
         default:
@@ -71,7 +71,7 @@ static void remove(Dict* args, void* vcontext, String* txid, struct Allocator* r
     struct Context* context = Identity_check((struct Context*) vcontext);
     String* user = Dict_getStringC(args, "user");
 
-    int32_t ret = CryptoAuth_removeUsers(context->ca, user);
+    int32_t ret = Ca_removeUsers(context->ca, user);
     if (ret) {
         sendResponse(String_CONST("none"), context->admin, txid, requestAlloc);
     } else {
@@ -86,19 +86,19 @@ 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 = Ca_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 < (int)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);
 }
 
 void AuthorizedPasswords_init(struct Admin* admin,
-                              struct CryptoAuth* ca,
+                              Ca_t* ca,
                               struct Allocator* allocator)
 {
     struct Context* context = Allocator_malloc(allocator, sizeof(struct Context));

+ 2 - 2
admin/AuthorizedPasswords.h

@@ -16,7 +16,7 @@
 #define AuthorizedPasswords_H
 
 #include "admin/Admin.h"
-#include "crypto/CryptoAuth.h"
+#include "crypto/Ca.h"
 #include "memory/Allocator.h"
 #include "util/Linker.h"
 Linker_require("admin/AuthorizedPasswords.c")
@@ -55,7 +55,7 @@ Linker_require("admin/AuthorizedPasswords.c")
  * @param allocator a persistent memory allocator.
  */
 void AuthorizedPasswords_init(struct Admin* admin,
-                              struct CryptoAuth* ca,
+                              Ca_t* ca,
                               struct Allocator* allocator);
 
 #endif

+ 4 - 2
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 {
@@ -343,7 +343,7 @@ void Core_init(struct Allocator* alloc,
         sec = Security_new(alloc, logger, eventBase);
     }
     struct GlobalConfig* globalConf = GlobalConfig_new(alloc);
-    struct NetCore* nc = NetCore_new(privateKey, alloc, eventBase, rand, logger);
+    struct NetCore* nc = NetCore_new(privateKey, alloc, eventBase, rand, logger, !Defined(NOISE_NO));
 
     struct RouteGen* rg = RouteGen_new(alloc, logger);
 
@@ -441,6 +441,7 @@ int Core_main(int argc, char** argv)
 
     struct Allocator* alloc = MallocAllocator_new(ALLOCATOR_FAILSAFE);
     struct Log* preLogger = FileWriterLog_new(stderr, alloc);
+    Rffi_setLogger(preLogger);
     struct EventBase* eventBase = EventBase_new(alloc);
 
     // -------------------- Setup the Pre-Logger ---------------------- //
@@ -513,6 +514,7 @@ int Core_main(int argc, char** argv)
         struct Log* adminLogger = AdminLog_registerNew(admin, alloc, rand, eventBase);
         IndirectLog_set(logger, adminLogger);
         logger = adminLogger;
+        Rffi_setLogger(logger);
     }
 
     // --------------------- Inform client of UDP Addr --------------------- //

+ 2 - 2
admin/angel/InterfaceWaiter.c

@@ -44,13 +44,13 @@ static void timeout(void* vcontext)
 static Iface_DEFUN receiveMessage(struct Message* message, struct Iface* iface)
 {
     struct Context* ctx = Identity_check((struct Context*) iface);
-    if (ctx->messageReceived) { return Error(NONE); }
+    if (ctx->messageReceived) { return NULL; }
     ctx->message = Message_clone(message, ctx->alloc);
 
     Timeout_clearTimeout(ctx->timeout);
     EventBase_endLoop(ctx->eventBase);
 
-    return Error(NONE);
+    return NULL;
 }
 
 struct Message* InterfaceWaiter_waitForData(struct Iface* iface,

+ 23 - 17
android_do

@@ -25,7 +25,7 @@ need rustc
 need cargo
 
 BUILD_PATH=$(pwd)/build_android
-NDK_VERSION="android-ndk-r21"
+NDK_VERSION="android-ndk-r25b"
 
 case $(uname -s) in
     Darwin)
@@ -70,10 +70,10 @@ cpu_arch="$(uname -m)"
 if test "x$CJDNS_NDK_PATH" = "x"; then
   mkdir "$BUILD_PATH" 2>/dev/null
   cd "$BUILD_PATH"
-  filename="$NDK_VERSION-${TYPE}-${cpu_arch}.zip"
+  filename="$NDK_VERSION-${TYPE}.zip"
   echo "$filename"
   if ! [ -f "$filename" ]; then
-    url="https://dl.google.com/android/repository/$NDK_VERSION-${TYPE}-${cpu_arch}.zip"
+    url="https://dl.google.com/android/repository/$NDK_VERSION-${TYPE}.zip"
     wget "$url" || die "wget $url failed"
   fi
   if ! [ -d "$NDK_VERSION" ]; then
@@ -86,41 +86,47 @@ fi
 
 BUILD_0='
   APP_ABI=armv7a
-  TOOLCHAIN_PREFIX=arm
+  RUST_TARGET=armv7-linux-androideabi
   EABI=androideabi
-  VERSION=16
+  VERSION=26
 '
 BUILD_1='
   APP_ABI=aarch64
-  VERSION=21
+  VERSION=26
 '
 BUILD_2='
   APP_ABI=i686
-  VERSION=16
+  VERSION=26
 '
 BUILD_3='
   APP_ABI=x86_64
-  VERSION=21
+  VERSION=26
 '
 
-for i in $(seq 1 100); do
+# https://github.com/rust-lang/rust/pull/85806
+find "${BUILD_PATH}" -name 'libunwind.a' | \
+  sed 's@libunwind.a$@libgcc.a@' | \
+  while read x; do
+    echo "INPUT(-lunwind)" > $x
+  done
+
+for i in $(seq 0 100); do
   BUILD=$(eval echo "\$BUILD_$i")
   if test "x$BUILD" = "x"; then
     continue
   fi
-  TOOLCHAIN_PREFIX=
+  RUST_TARGET=
   APP_ABI=
   VERSION=
   EABI=android
   export $BUILD
-  if test "x$TOOLCHAIN_PREFIX" = "x"; then
-    TOOLCHAIN_PREFIX=$APP_ABI
+  if test "x$RUST_TARGET" = "x"; then
+    RUST_TARGET="$APP_ABI-linux-$EABI"
   fi
 
-  RUST_TARGET="$APP_ABI-linux-$EABI"
   if ! [ -d "$(rustc --target "$RUST_TARGET" --print target-libdir)" ]; then
     echo
-    echo 'Skipping i686-linux-android because we dont have that toolchain'
+    echo "Skipping $RUST_TARGET because we dont have that toolchain"
     echo "Use: \`rustup target add $RUST_TARGET\` to install it"
     echo
     echo
@@ -128,7 +134,7 @@ for i in $(seq 1 100); do
   fi
 
   CROSS_PATH=$CJDNS_NDK_PATH/toolchains/llvm/prebuilt/${TYPE}-${cpu_arch}/bin
-  CROSS_PREFIX=${CROSS_PATH}/${TOOLCHAIN_PREFIX}-linux-${EABI}
+  CROSS_PREFIX=${CROSS_PATH}/llvm
 
   export CC=${CROSS_PATH}/${APP_ABI}-linux-${EABI}${VERSION}-clang
 
@@ -144,8 +150,8 @@ for i in $(seq 1 100); do
   export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=$CC
   export CARGO_TARGET_I686_LINUX_ANDROID_LINKER=$CC
   export CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=$CC
-  export CARGO_TARGET_ARMV7A_LINUX_ANDROIDEABI_LINKER=$CC
+  export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER=$CC
 
   echo "Compiler CC: $CC - $(${CC} --version)"
-  cargo build --release -vv --target "$RUST_TARGET"
+  cargo build --release -v --target "$RUST_TARGET"
 done

+ 4 - 2
benc/Object.h

@@ -15,18 +15,20 @@
 #ifndef Object_H
 #define Object_H
 
-#include <inttypes.h>
+#include <stdint.h>
 
 #include "memory/Allocator.h"
 
 // Dictionaries and lists are pointers to the head entry so that the head can change.
 typedef struct Dict_Entry* Dict;
 typedef struct List_Item* List;
-typedef struct {
+typedef struct String_s {
     uintptr_t len;
     char* bytes;
 } String;
 
+typedef String String_t;
+
 enum Object_Type {
     Object_INTEGER,
     Object_STRING,

+ 9 - 9
benc/serialization/json/JsonBencMessageReader.c

@@ -36,7 +36,7 @@ struct Context {
 
 static int getColumn(struct Context* ctx)
 {
-    return (uintptr_t) ctx->msg->bytes - ctx->beginningLastLine;
+    return (uintptr_t) ctx->msg->msgbytes - ctx->beginningLastLine;
 }
 
 #define ERROR0(ctx, message) \
@@ -50,16 +50,16 @@ static int getColumn(struct Context* ctx)
 
 static Er_DEFUN(uint8_t peak(struct Context* ctx))
 {
-    if (!ctx->msg->length) { ERROR0(ctx, "Out of content while reading"); }
-    Er_ret(ctx->msg->bytes[0]);
+    if (!Message_getLength(ctx->msg)) { ERROR0(ctx, "Out of content while reading"); }
+    Er_ret(ctx->msg->msgbytes[0]);
 }
 
 static Er_DEFUN(void skip(struct Context* ctx, int num))
 {
-    if (num > ctx->msg->length) { ERROR0(ctx, "Out of content while reading"); }
+    if (num > Message_getLength(ctx->msg)) { ERROR0(ctx, "Out of content while reading"); }
     for (int i = 0; i < num; i++) {
-        if (ctx->msg->bytes[i] == '\n') {
-            ctx->beginningLastLine = (uintptr_t) &ctx->msg->bytes[i];
+        if (ctx->msg->msgbytes[i] == '\n') {
+            ctx->beginningLastLine = (uintptr_t) &ctx->msg->msgbytes[i];
             ctx->line++;
         }
     }
@@ -126,7 +126,7 @@ static Er_DEFUN(String* parseString(struct Context* ctx))
     Er(assertChar(ctx, '"', false));
     int line = ctx->line;
     uintptr_t beginningLastLine = ctx->beginningLastLine;
-    int msgLen = ctx->msg->length;
+    int msgLen = Message_getLength(ctx->msg);
 
     String* out = NULL;
     uint32_t pos = 0;
@@ -149,7 +149,7 @@ static Er_DEFUN(String* parseString(struct Context* ctx))
                 // got the length, reset and then copy the string next cycle
                 ctx->line = line;
                 ctx->beginningLastLine = beginningLastLine;
-                Er(Message_eshift(ctx->msg, msgLen - ctx->msg->length));
+                Er(Message_eshift(ctx->msg, msgLen - Message_getLength(ctx->msg)));
                 out = String_newBinary(NULL, pos, ctx->alloc);
                 pos = 0;
                 continue;
@@ -314,7 +314,7 @@ Er_DEFUN(Dict* JsonBencMessageReader_read(
         .alloc = alloc,
         .lax = lax,
         .line = 1,
-        .beginningLastLine = (uintptr_t) msg->bytes
+        .beginningLastLine = (uintptr_t) msg->msgbytes
     };
     Er_ret( Er(parseDict(&ctx)) );
 }

+ 2 - 2
benc/serialization/standard/BencMessageReader.c

@@ -28,7 +28,7 @@ static Er_DEFUN(int64_t readInt(struct Message* msg, struct Allocator* alloc))
 {
     int64_t num = Er(Base10_read(msg));
     if (Er(Message_epop8(msg)) != 'e') {
-        Er_raise(msg->alloc, "Int not terminated with 'e'");
+        Er_raise(Message_getAlloc(msg), "Int not terminated with 'e'");
     }
     Er_ret(num);
 }
@@ -42,7 +42,7 @@ static Er_DEFUN(String* readString(struct Message* msg, struct Allocator* alloc)
     if (Er(Message_epop8(msg)) != ':') {
         Er_raise(alloc, "String not deliniated with a ':'");
     }
-    if (len > msg->length) {
+    if (len > Message_getLength(msg)) {
         Er_raise(alloc, "String too long");
     }
     String* str = String_newBinary(NULL, len, alloc);

+ 4 - 4
benc/serialization/standard/BencMessageWriter.c

@@ -90,15 +90,15 @@ Er_DEFUN(void BencMessageWriter_write(Dict* toWrite, struct Message* msg))
     Er(writeDict(toWrite, msg));
 
     // lucky
-    if (!((uintptr_t)msg->bytes % 8)) { Er_ret(); }
+    if (!((uintptr_t)msg->msgbytes % 8)) { Er_ret(); }
 
     char d = Er(Message_epop8(msg));
     Assert_true(d == 'd');
-    Assert_true(msg->bytes[0] != 'e' && "Can't serialize empty messages");
-    Assert_true(msg->bytes[0] >= '1' && msg->bytes[0] <= '9');
+    Assert_true(msg->msgbytes[0] != 'e' && "Can't serialize empty messages");
+    Assert_true(msg->msgbytes[0] >= '1' && msg->msgbytes[0] <= '9');
 
     // put the message into alignment by padding out the number with leading zeros :)
-    do { Er(Message_epush8(msg, '0')); } while ((uintptr_t)msg->bytes % 8);
+    do { Er(Message_epush8(msg, '0')); } while ((uintptr_t)msg->msgbytes % 8);
 
     Er(Message_epop8(msg));
     Er(Message_epush8(msg, 'd'));

+ 15 - 13
client/AdminClient.c

@@ -23,6 +23,7 @@
 #include "util/events/Timeout.h"
 #include "util/Identity.h"
 #include "wire/Message.h"
+#include "wire/Error.h"
 
 #include <sodium/crypto_hash_sha256.h>
 
@@ -93,7 +94,7 @@ static int calculateAuth(Dict* message,
     Er_assert(BencMessageWriter_write(message, msg));
 
     // calculate the hash of the message with the password hash
-    crypto_hash_sha256(hash, msg->bytes, msg->length);
+    crypto_hash_sha256(hash, msg->msgbytes, Message_getLength(msg));
 
     // swap the hash of the message with the password hash into the location
     // where the password hash was.
@@ -121,30 +122,30 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* addrIface)
     Er_assert(Message_epop(msg, &source, ctx->targetAddr->addrLen));
     if (Bits_memcmp(&source, ctx->targetAddr, ctx->targetAddr->addrLen)) {
         Log_info(ctx->logger, "Got spurious message from [%s], expecting messages from [%s]",
-                 Sockaddr_print(&source.addr, msg->alloc),
-                 Sockaddr_print(ctx->targetAddr, msg->alloc));
+                 Sockaddr_print(&source.addr, Message_getAlloc(msg)),
+                 Sockaddr_print(ctx->targetAddr, Message_getAlloc(msg)));
         // The UDP interface can't make use of an error but we'll inform anyway
-        return Error(INVALID);
+        return Error(msg, "INVALID source addr");
     }
 
     // we don't yet know with which message this data belongs,
     // the message alloc lives the length of the message reception.
-    struct Allocator* alloc = Allocator_child(msg->alloc);
+    struct Allocator* alloc = Allocator_child(Message_getAlloc(msg));
 
-    int origLen = msg->length;
+    int origLen = Message_getLength(msg);
     Dict* d = NULL;
     const char* err = BencMessageReader_readNoExcept(msg, alloc, &d);
-    if (err) { return Error(INVALID); }
+    if (err) { return Error(msg, "Error decoding benc: %s", err); }
     Er_assert(Message_eshift(msg, origLen));
 
     String* txid = Dict_getStringC(d, "txid");
-    if (!txid || txid->len != 8) { return Error(INVALID); }
+    if (!txid || txid->len != 8) { return Error(msg, "INVALID missing or wrong size txid"); }
 
     // look up the result
     uint32_t handle = ~0u;
     Hex_decode((uint8_t*)&handle, 4, txid->bytes, 8);
     int idx = Map_OfRequestByHandle_indexForHandle(handle, &ctx->outstandingRequests);
-    if (idx < 0) { return Error(INVALID); }
+    if (idx < 0) { return Error(msg, "INVALID no such handle"); }
 
     struct Request* req = ctx->outstandingRequests.values[idx];
 
@@ -153,12 +154,13 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* addrIface)
 
     req->res.responseDict = d;
 
-    int len =
-        (msg->length > AdminClient_MAX_MESSAGE_SIZE) ? AdminClient_MAX_MESSAGE_SIZE : msg->length;
+    int len = (Message_getLength(msg) > AdminClient_MAX_MESSAGE_SIZE)
+        ? AdminClient_MAX_MESSAGE_SIZE
+        : Message_getLength(msg);
     Bits_memset(req->res.messageBytes, 0, AdminClient_MAX_MESSAGE_SIZE);
-    Bits_memcpy(req->res.messageBytes, msg->bytes, len);
+    Bits_memcpy(req->res.messageBytes, msg->msgbytes, len);
     done(req, AdminClient_Error_NONE);
-    return Error(NONE);
+    return NULL;
 }
 
 static int requestOnFree(struct Allocator_OnFreeJob* job)

+ 13 - 17
client/cjdroute2.c

@@ -28,7 +28,7 @@
 #include "benc/serialization/standard/BencMessageWriter.h"
 #include "crypto/random/test/DeterminentRandomSeed.h"
 #include "crypto/AddressCalc.h"
-#include "crypto/CryptoAuth.h"
+#include "crypto/Ca.h"
 #include "dht/Address.h"
 #include "exception/Except.h"
 #include "interface/Iface.h"
@@ -55,7 +55,6 @@
 #include "util/log/FileWriterLog.h"
 #include "util/SysInfo.h"
 #include "util/version/Version.h"
-#include "net/Benchmark.h"
 
 #include <stdint.h>
 #include <stdio.h>
@@ -77,7 +76,7 @@ static int genconf(struct Allocator* alloc, struct Random* rand, bool eth, bool
         uint8_t seedbuf[64];
         Bits_memset(seedbuf, 0, 64);
         Assert_true(64 == read(STDIN_FILENO, seedbuf, 64));
-        struct RandomSeed* rs = DeterminentRandomSeed_new(alloc, seedbuf);
+        RandomSeed_t* rs = DeterminentRandomSeed_new(alloc, seedbuf);
         rand = Random_newWithSeed(alloc, NULL, rs, NULL);
     }
 
@@ -220,10 +219,11 @@ static int genconf(struct Allocator* alloc, struct Random* rand, bool eth, bool
            "                    // Add connection credentials here to join the network\n"
            "                    // Ask somebody who is already connected.\n"
            "                }\n"
-           "            }\n"
-           "        ],\n\n");
+           "            }\n");
 #ifdef HAS_ETH_INTERFACE
-    printf("        // The interface which allows peering using layer-2 ethernet frames\n"
+
+    printf("        ],\n\n"
+           "        // The interface which allows peering using layer-2 ethernet frames\n"
            "        \"%sETHInterface\": [\n"
            "            // Alternatively bind to just one device and either beacon and/or\n"
            "            // connect to a specified MAC address\n"
@@ -356,7 +356,7 @@ static int genconf(struct Allocator* alloc, struct Random* rand, bool eth, bool
            "        // and ETHInterface will be unable to hot-add new interfaces\n"
            "        // Use { \"setuser\": 0 } to disable.\n"
            "        // Default: enabled with keepNetAdmin\n");
-           if (Defined(android) || Defined(darwin)) {
+           if (Defined(Cjdns_android) || Defined(darwin)) {
     printf("        { \"setuser\": 0 },\n");
            } else {
     printf("        { \"setuser\": \"nobody\", \"keepNetAdmin\": 1 },\n");
@@ -366,7 +366,7 @@ static int genconf(struct Allocator* alloc, struct Random* rand, bool eth, bool
            "        // from accessing files outside of the chroot sandbox, if the user does not\n"
            "        // have permission to use chroot(), this will fail quietly.\n"
            "        // Use { \"chroot\": 0 } to disable.\n");
-          if (Defined(android)) {
+          if (Defined(Cjdns_android)) {
     printf("        // Default: disabled\n"
            "        { \"chroot\": 0 },\n");
           }
@@ -391,7 +391,7 @@ static int genconf(struct Allocator* alloc, struct Random* rand, bool eth, bool
            "        // SECCOMP_BPF to filter the system calls which cjdns is able to make on a\n"
            "        // linux system, strictly limiting it's access to the outside world\n"
            "        // This will fail quietly on any non-linux system\n");
-          if (Defined(android)) {
+          if (Defined(Cjdns_android)) {
     printf("        // Default: disabled\n"
            "        { \"seccomp\": 0 },\n");
           }
@@ -447,7 +447,6 @@ static int usage(struct Allocator* alloc, char* appName)
            "                                   beaconing\n"
            "    cjdroute --genconf-seed [--eth] Generate a configuration file from a 64 byte seed\n"
            "                                   which is read in from stdin."
-           "    cjdroute --bench               Run some cryptography performance benchmarks.\n"
            "    cjdroute --version             Print the protocol version which this node speaks.\n"
            "    cjdroute --cleanconf < conf    Print a clean (valid json) version of the config.\n"
            "    cjdroute --nobg                Never fork to the background no matter the config.\n"
@@ -579,7 +578,7 @@ static String* getPipePath(Dict* config, struct Allocator* alloc)
         return pipePath;
     }
     char* path = Pipe_PATH;
-    if (Defined(android)) {
+    if (Defined(Cjdns_android)) {
         char* t = getenv("TMPDIR");
         if (!t) {
             t = getenv("HOME");
@@ -623,9 +622,6 @@ int cjdroute2_main(int argc, char** argv)
             return genconf(allocator, rand, 0, 1);
         } else if (CString_strcmp(argv[1], "--genconf") == 0) {
             return genconf(allocator, rand, 0, 0);
-        } else if (CString_strcmp(argv[1], "--bench") == 0) {
-            Benchmark_runAll();
-            return 0;
         } else if ((CString_strcmp(argv[1], "--version") == 0)
             || (CString_strcmp(argv[1], "-v") == 0))
         {
@@ -681,7 +677,7 @@ int cjdroute2_main(int argc, char** argv)
     // and if the old parser fails or the parsed content contains "version": 2,
     // fail to launch
     struct Message* confMsg = readToMsg(stdin, allocator);
-    struct Reader* confReader = ArrayReader_new(confMsg->bytes, confMsg->length, allocator);
+    struct Reader* confReader = ArrayReader_new(confMsg->msgbytes, Message_getLength(confMsg), allocator);
     Dict _config;
     Dict* config = &_config;
     const char* err = JsonBencMessageReader_readNoExcept(confMsg, allocator, &config, false);
@@ -774,7 +770,7 @@ int cjdroute2_main(int argc, char** argv)
     if (!privateKey) {
         Except_throw(eh, "Need to specify privateKey.");
     }
-    Process_spawn(corePath, args, eventBase, allocator, onCoreExit);
+    Process_spawn(corePath, args, allocator, onCoreExit);
 
     // --------------------- Wait for socket ------------------------- //
     // cycle for up to 1 minute
@@ -813,7 +809,7 @@ int cjdroute2_main(int argc, char** argv)
     Er_assert(BencMessageWriter_write(preConf, toCoreMsg));
     Iface_CALL(corePipe->iface.send, toCoreMsg, &corePipe->iface);
 
-    Log_debug(logger, "Sent [%d] bytes to core", toCoreMsg->length);
+    Log_debug(logger, "Sent [%d] bytes to core", Message_getLength(toCoreMsg));
 
     // --------------------- Get Response from Core --------------------- //
 

+ 1 - 0
contrib/c/mkpasswd.c

@@ -23,6 +23,7 @@
 int mkpasswd_main(int argc, char** argv);
 int mkpasswd_main(int argc, char** argv)
 {
+    fprintf(stderr, "mkpasswd is deprecated and will be removed from the next release\n");
     struct Allocator* alloc = MallocAllocator_new(1<<22);
     struct Random* rand = Random_new(alloc, NULL, NULL);
 

+ 1 - 1
contrib/c/privatetopublic.c

@@ -47,7 +47,7 @@ static int usage(char* appName)
 int privatetopublic_main(int argc, char** argv);
 int privatetopublic_main(int argc, char** argv)
 {
-    struct Address address;
+    struct Address address = {0};
     uint8_t addressOut[40];
     uint8_t privateKey[32];
     uint8_t publicKeyBase32Out[53];

+ 1 - 0
contrib/c/sybilsim.c

@@ -439,6 +439,7 @@ static int usage(char* appName)
 int sybilsim_main(int argc, char** argv);
 int sybilsim_main(int argc, char** argv)
 {
+    fprintf(stderr, "sybilsim is deprecated and will be removed from the next release\n");
     Assert_true(argc > 0);
     if (isatty(STDIN_FILENO)) {
         return usage(argv[0]);

+ 1 - 1
contrib/simple-install/README.md

@@ -6,7 +6,7 @@ Tested on ubuntu 18.04LTS
 git clone https://github.com/cjdelisle/cjdns.git
 cd cjdns/
 ./do
-sudo ./contrib/simple-install/cjdns-install.sh
+sudo ./contrib/simple-install/cjdns-installer.sh
 ```
 
 You can edit configuration in `/etc/cjdroute.conf` and restart cjdns service with `sudo systemctl restart cjdns.service`.

+ 1 - 0
contrib/simple-install/cjdns-installer.sh

@@ -7,4 +7,5 @@ cp publictoip6 /usr/bin/
 cp randombytes /usr/bin/
 cp sybilsim /usr/bin/
 cp contrib/systemd/cjdns.service /etc/systemd/system/
+cp contrib/systemd/cjdns-resume.service /etc/systemd/system
 systemctl enable --now cjdns.service

+ 186 - 0
crypto/Ca.h

@@ -0,0 +1,186 @@
+/* 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 Ca_H
+#define Ca_H
+
+#include "rust/cjdns_sys/RTypes.h"
+#include "benc/String.h"
+#include "crypto/random/Random.h"
+#include "memory/Allocator.h"
+#include "util/log/Log.h"
+#include "util/events/EventBase.h"
+
+#ifndef OLD_CA
+#include "rust/cjdns_sys/Rffi.h"
+typedef RTypes_CryptoAuth2_t Ca_t;
+typedef RTypes_CryptoAuth2_Session_t Ca_Session_t;
+#define Ca_IMPL(x) Rffi_CryptoAuth2_ ## x
+static inline Ca_t* Ca_new(struct Allocator* allocator,
+                                  const uint8_t* privateKey,
+                                  struct EventBase* eventBase,
+                                  struct Log* logger,
+                                  struct Random* rand)
+{
+    return Rffi_CryptoAuth2_new(allocator, privateKey, rand);
+}
+#else
+#include "crypto/CryptoAuth.h"
+typedef struct CryptoAuth Ca_t;
+typedef struct CryptoAuth_Session Ca_Session_t;
+#define Ca_IMPL(x) CryptoAuth_ ## x
+#define Ca_new CryptoAuth_new
+#endif
+
+enum Ca_addUser_Res {
+    Ca_addUser_DUPLICATE = -3,
+};
+static inline int Ca_addUser_ipv6(String* password,
+                            String* login,
+                            uint8_t ipv6[16],
+                            Ca_t* ca)
+{
+    return Ca_IMPL(addUser_ipv6)(password, login, ipv6, ca);
+}
+static inline int Ca_addUser(String* password, String* login, Ca_t* ca)
+{
+    return Ca_addUser_ipv6(password, login, NULL, ca);
+}
+static inline int Ca_removeUsers(Ca_t* context, String* user)
+{
+    return Ca_IMPL(removeUsers)(context, user);
+}
+static inline RTypes_StrList_t* Ca_getUsers(const Ca_t* context, struct Allocator* alloc)
+{
+    return Ca_IMPL(getUsers)(context, alloc);
+}
+static inline Ca_Session_t* Ca_newSession(Ca_t* ca,
+                                          struct Allocator* alloc,
+                                          const uint8_t herPublicKey[32],
+                                          const bool requireAuth,
+                                          const char* name,
+                                          bool useNoise)
+{
+    return Ca_IMPL(newSession)(ca, alloc, herPublicKey, requireAuth, name, useNoise);
+}
+static inline void Ca_setAuth(const String* password,
+                              const String* login,
+                              Ca_Session_t* caSession)
+{
+    Ca_IMPL(setAuth)(password, login, caSession);
+}
+static inline void Ca_resetIfTimeout(Ca_Session_t* session)
+{
+    Ca_IMPL(resetIfTimeout)(session);
+}
+static inline void Ca_reset(Ca_Session_t* caSession)
+{
+    Ca_IMPL(reset)(caSession);
+}
+static inline RTypes_CryptoAuth_State_t Ca_getState(Ca_Session_t* session)
+{
+    return Ca_IMPL(getState)(session);
+}
+static inline void Ca_getHerPubKey(const Ca_Session_t* session, uint8_t *pkOut)
+{
+    Ca_IMPL(getHerPubKey)(session, pkOut);
+}
+static inline void Ca_getHerIp6(const Ca_Session_t* session, uint8_t *ipOut)
+{
+    Ca_IMPL(getHerIp6)(session, ipOut);
+}
+static inline void Ca_getPubKey(const Ca_t* ca, uint8_t *pkOut)
+{
+    Ca_IMPL(getPubKey)(ca, pkOut);
+}
+static inline String_t *Ca_getName(const Ca_Session_t* session, Allocator_t *alloc)
+{
+    return Ca_IMPL(getName)(session, alloc);
+}
+static inline void Ca_stats(const Ca_Session_t* session, RTypes_CryptoStats_t *statsOut)
+{
+    Ca_IMPL(stats)(session, statsOut);
+}
+
+
+enum Ca_DecryptErr {
+    Ca_DecryptErr_NONE = 0,
+
+    // Packet too short
+    Ca_DecryptErr_RUNT = 1,
+
+    // Received a run message to an un-setup session
+    Ca_DecryptErr_NO_SESSION = 2,
+
+    Ca_DecryptErr_FINAL_SHAKE_FAIL = 3,
+
+    Ca_DecryptErr_FAILED_DECRYPT_RUN_MSG = 4,
+
+    Ca_DecryptErr_KEY_PKT_ESTABLISHED_SESSION = 5,
+
+    Ca_DecryptErr_WRONG_PERM_PUBKEY = 6,
+
+    // Only specific IPv6 can connect to this CA session and the request has the wrong one.
+    Ca_DecryptErr_IP_RESTRICTED = 7,
+
+    // Authentication is required and is missing.
+    Ca_DecryptErr_AUTH_REQUIRED = 8,
+
+    // Basically this means the login name doesn't exist, beware of giving this information up.
+    Ca_DecryptErr_UNRECOGNIZED_AUTH = 9,
+
+    // Key packet and we are not in a state to accept a key packet
+    Ca_DecryptErr_STRAY_KEY = 10,
+
+    Ca_DecryptErr_HANDSHAKE_DECRYPT_FAILED = 11,
+
+    // Set zero as the temporary public key
+    Ca_DecryptErr_WISEGUY = 12,
+
+    // Duplicate hello or key packet (same temp key and not a repeat-packet type)
+    // Or repeat key packet with different key than what is known
+    // Or a repeat hello packet for which we already know the temp key (meaning it is associated
+    // with an existing session) when we are not in a state to accept a repeat hello.
+    Ca_DecryptErr_INVALID_PACKET = 13,
+
+    // Replay checker could not validate this packet
+    Ca_DecryptErr_REPLAY = 14,
+
+    // Authenticated decryption failed
+    Ca_DecryptErr_DECRYPT = 15
+};
+
+
+
+#define Ca_State_INIT           RTypes_CryptoAuth_State_t_Init
+#define Ca_State_SENT_HELLO     RTypes_CryptoAuth_State_t_SentHello
+#define Ca_State_RECEIVED_HELLO RTypes_CryptoAuth_State_t_ReceivedHello
+#define Ca_State_SENT_KEY       RTypes_CryptoAuth_State_t_SentKey
+#define Ca_State_RECEIVED_KEY   RTypes_CryptoAuth_State_t_ReceivedKey
+#define Ca_State_ESTABLISHED    RTypes_CryptoAuth_State_t_Established
+
+static inline char* Ca_stateString(RTypes_CryptoAuth_State_t state)
+{
+    switch (state) {
+        case Ca_State_INIT:           return "INIT";
+        case Ca_State_SENT_HELLO:     return "SENT_HELLO";
+        case Ca_State_RECEIVED_HELLO: return "RECEIVED_HELLO";
+        case Ca_State_SENT_KEY:       return "SENT_KEY";
+        case Ca_State_RECEIVED_KEY:   return "RECEIVED_KEY";
+        case Ca_State_ESTABLISHED:    return "ESTABLISHED";
+        default: return "INVALID";
+    }
+}
+
+#endif

+ 169 - 68
crypto/CryptoAuth.c

@@ -179,21 +179,21 @@ static inline struct CryptoAuth_User* getAuth(struct CryptoHeader_Challenge* aut
  * @param secret a shared secret.
  * @return 0 if decryption is succeddful, otherwise -1.
  */
-static inline Gcc_USE_RET int decryptRndNonce(uint8_t nonce[24],
+static inline Gcc_USE_RET int decryptRndNonce(const uint8_t nonce[24],
                                               struct Message* msg,
-                                              uint8_t secret[32])
+                                              const uint8_t secret[32])
 {
-    if (msg->length < 16) {
+    if (Message_getLength(msg) < 16) {
         return -1;
     }
-    Assert_true(msg->padding >= 16);
-    uint8_t* startAt = msg->bytes - 16;
+    Assert_true(Message_getPadding(msg) >= 16);
+    uint8_t* startAt = msg->msgbytes - 16;
     uint8_t paddingSpace[16];
     Bits_memcpy(paddingSpace, startAt, 16);
     Bits_memset(startAt, 0, 16);
     if (!Defined(NSA_APPROVED)) {
         if (crypto_box_curve25519xsalsa20poly1305_open_afternm(
-                startAt, startAt, msg->length + 16, nonce, secret) != 0)
+                startAt, startAt, Message_getLength(msg) + 16, nonce, secret) != 0)
         {
             return -1;
         }
@@ -212,19 +212,19 @@ static inline Gcc_USE_RET int decryptRndNonce(uint8_t nonce[24],
  * @param msg a message to encipher and authenticate.
  * @param secret a shared secret.
  */
-static inline void encryptRndNonce(uint8_t nonce[24],
+static inline void encryptRndNonce(const uint8_t nonce[24],
                                    struct Message* msg,
-                                   uint8_t secret[32])
+                                   const uint8_t secret[32])
 {
-    Assert_true(msg->padding >= 32);
-    uint8_t* startAt = msg->bytes - 32;
+    Assert_true(Message_getPadding(msg) >= 32);
+    uint8_t* startAt = msg->msgbytes - 32;
     // This function trashes 16 bytes of the padding so we will put it back
     uint8_t paddingSpace[16];
     Bits_memcpy(paddingSpace, startAt, 16);
     Bits_memset(startAt, 0, 32);
     if (!Defined(NSA_APPROVED)) {
         crypto_box_curve25519xsalsa20poly1305_afternm(
-            startAt, startAt, msg->length + 32, nonce, secret);
+            startAt, startAt, Message_getLength(msg) + 32, nonce, secret);
     }
 
     Bits_memcpy(startAt, paddingSpace, 16);
@@ -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)
@@ -325,10 +325,10 @@ static void resetIfTimeout(struct CryptoAuth_Session_pvt* session)
         return;
     }
 
-    uint64_t nowSecs = Time_currentTimeSeconds(session->context->eventBase);
-    if (nowSecs - session->timeOfLastPacket < session->pub.setupResetAfterInactivitySeconds) {
+    uint64_t nowSecs = Time_currentTimeSeconds();
+    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; }
     }
 
@@ -345,14 +345,14 @@ static void encryptHandshake(struct Message* message,
 {
     Er_assert(Message_eshift(message, CryptoHeader_SIZE));
 
-    struct CryptoHeader* header = (struct CryptoHeader*) message->bytes;
+    struct CryptoHeader* header = (struct CryptoHeader*) message->msgbytes;
 
     // garbage the auth challenge and set the nonce which follows it
     Random_bytes(session->context->rand, (uint8_t*) &header->auth,
                  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);
 
@@ -459,7 +459,7 @@ static void encryptHandshake(struct Message* message,
         uint8_t nonceHex[49];
         Hex_encode(nonceHex, 49, header->handshakeNonce, 24);
         uint8_t cipherHex[65];
-        printHexKey(cipherHex, message->bytes);
+        printHexKey(cipherHex, message->msgbytes);
         Log_keys(session->context->logger,
                   "Encrypting message with:\n"
                   "    nonce: %s\n"
@@ -473,11 +473,8 @@ static void encryptHandshake(struct Message* message,
 }
 
 /** @return 0 on success, -1 otherwise. */
-int CryptoAuth_encrypt(struct CryptoAuth_Session* sessionPub, struct Message* msg)
+static int encryptPacket(struct CryptoAuth_Session_pvt* session, struct Message* msg)
 {
-    struct CryptoAuth_Session_pvt* session =
-        Identity_check((struct CryptoAuth_Session_pvt*) sessionPub);
-
     // If there has been no incoming traffic for a while, reset the connection to state 0.
     // This will prevent "connection in bad state" situations from lasting forever.
     // this will reset the session if it has timed out.
@@ -488,7 +485,7 @@ int CryptoAuth_encrypt(struct CryptoAuth_Session* sessionPub, struct Message* ms
         reset(session);
     }
 
-    Assert_true(!((uintptr_t)msg->bytes % 4) || !"alignment fault");
+    Assert_true(!((uintptr_t)msg->msgbytes % 4) || !"alignment fault");
 
     // nextNonce 0: sending hello, we are initiating connection.
     // nextNonce 1: sending another hello, nothing received yet.
@@ -514,8 +511,8 @@ int CryptoAuth_encrypt(struct CryptoAuth_Session* sessionPub, struct Message* ms
         }
     }
 
-    Assert_true(msg->length > 0 && "Empty packet during handshake");
-    Assert_true(msg->padding >= 36 || !"not enough padding");
+    Assert_true(Message_getLength(msg) > 0 && "Empty packet during handshake");
+    Assert_true(Message_getPadding(msg) >= 36 || !"not enough padding");
 
     encrypt(session->nextNonce, msg, session->sharedSecret, session->isInitiator);
 
@@ -524,10 +521,17 @@ int CryptoAuth_encrypt(struct CryptoAuth_Session* sessionPub, struct Message* ms
     return 0;
 }
 
+/** @return 0 on success, -1 otherwise. */ // Now only used in unit tests on Rust side
+int CryptoAuth_encrypt(struct CryptoAuth_Session* sessionPub, struct Message* msg) {
+    struct CryptoAuth_Session_pvt *session =
+            Identity_check((struct CryptoAuth_Session_pvt *) sessionPub);
+    return encryptPacket(session, msg);
+}
+
 /** Call the external interface and tell it that a message has been received. */
 static inline void updateTime(struct CryptoAuth_Session_pvt* session, struct Message* message)
 {
-    session->timeOfLastPacket = Time_currentTimeSeconds(session->context->eventBase);
+    session->timeOfLastPacket = Time_currentTimeSeconds();
 }
 
 static inline enum CryptoAuth_DecryptErr decryptMessage(struct CryptoAuth_Session_pvt* session,
@@ -540,7 +544,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;
     }
@@ -559,7 +563,7 @@ static enum CryptoAuth_DecryptErr decryptHandshake(struct CryptoAuth_Session_pvt
                                                    struct Message* message,
                                                    struct CryptoHeader* header)
 {
-    if (message->length < CryptoHeader_SIZE) {
+    if (Message_getLength(message) < CryptoHeader_SIZE) {
         cryptoAuthDebug0(session, "DROP runt");
         return CryptoAuth_DecryptErr_RUNT;
     }
@@ -572,7 +576,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 +591,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 +618,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 +636,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;
@@ -647,7 +651,7 @@ static enum CryptoAuth_DecryptErr decryptHandshake(struct CryptoAuth_Session_pvt
         uint8_t nonceHex[49];
         Hex_encode(nonceHex, 49, header->handshakeNonce, 24);
         uint8_t cipherHex[65];
-        printHexKey(cipherHex, message->bytes);
+        printHexKey(cipherHex, message->msgbytes);
         Log_keys(session->context->logger,
                   "Decrypting message with:\n"
                   "    nonce: %s\n"
@@ -762,8 +766,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,26 +828,24 @@ 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;
 }
 
 /** @return 0 on success, -1 otherwise. */
-enum CryptoAuth_DecryptErr CryptoAuth_decrypt(struct CryptoAuth_Session* sessionPub,
-                                              struct Message* msg)
+static enum CryptoAuth_DecryptErr decryptPacket(struct CryptoAuth_Session_pvt* session,
+                                                struct Message* msg)
 {
-    struct CryptoAuth_Session_pvt* session =
-        Identity_check((struct CryptoAuth_Session_pvt*) sessionPub);
-    struct CryptoHeader* header = (struct CryptoHeader*) msg->bytes;
+    struct CryptoHeader* header = (struct CryptoHeader*) msg->msgbytes;
 
-    if (msg->length < 20) {
+    if (Message_getLength(msg) < 20) {
         cryptoAuthDebug0(session, "DROP runt");
         return CryptoAuth_DecryptErr_RUNT;
     }
-    Assert_true(msg->padding >= 12 || "need at least 12 bytes of padding in incoming message");
-    Assert_true(!((uintptr_t)msg->bytes % 4) || !"alignment fault");
-    Assert_true(!(msg->capacity % 4) || !"length fault");
+    Assert_true(Message_getPadding(msg) >= 12 || "need at least 12 bytes of padding in incoming message");
+    Assert_true(!((uintptr_t)msg->msgbytes % 4) || !"alignment fault");
+    Assert_true(!(Message_getCapacity(msg) % 4) || !"length fault");
 
     Er_assert(Message_eshift(msg, -4));
 
@@ -869,8 +871,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");
@@ -911,6 +913,14 @@ enum CryptoAuth_DecryptErr CryptoAuth_decrypt(struct CryptoAuth_Session* session
     Assert_failure("unreachable");
 }
 
+/** @return 0 on success, -1 otherwise. */ // Now only used in unit tests on Rust side
+enum CryptoAuth_DecryptErr CryptoAuth_decrypt(struct CryptoAuth_Session* sessionPub,
+                                              struct Message* msg) {
+    struct CryptoAuth_Session_pvt *session =
+            Identity_check((struct CryptoAuth_Session_pvt *) sessionPub);
+    return decryptPacket(session, msg);
+}
+
 /////////////////////////////////////////////////////////////////////////////////////////////////
 
 struct CryptoAuth* CryptoAuth_new(struct Allocator* allocator,
@@ -931,11 +941,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,43 +1033,90 @@ 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) {
-        StringList_add(users, String_clone(u->login, alloc));
+        count++;
     }
 
-    return users;
+    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) {
+        out->items[i] = String_clone(u->login, alloc);
+        i++;
+    }
+
+    return out;
+}
+
+static Iface_DEFUN plaintextMsg(struct Message* msg, struct Iface* iface)
+{
+    struct CryptoAuth_Session_pvt* sess =
+        Identity_containerOf(iface, struct CryptoAuth_Session_pvt, pub.plaintext);
+    if (encryptPacket(sess, msg)) {
+        return Error(msg, "INTERNAL");
+    }
+    return Iface_next(&sess->pub.ciphertext, msg);
+}
+
+static Iface_DEFUN ciphertextMsg(struct Message* msg, struct Iface* iface)
+{
+    struct CryptoAuth_Session_pvt* sess =
+        Identity_containerOf(iface, struct CryptoAuth_Session_pvt, pub.ciphertext);
+    if (Message_getLength(msg) < 32) {
+        return Error(msg, "RUNT");
+    }
+    // Address is pushed on top of the message
+    Er_assert(Message_epop(msg, NULL, 16));
+    uint8_t firstSixteen[16];
+    Bits_memcpy(firstSixteen, msg->msgbytes, 16);
+    enum CryptoAuth_DecryptErr e = decryptPacket(sess, msg);
+    if (e == CryptoAuth_DecryptErr_NONE) {
+        Er_assert(Message_epush32be(msg, CryptoAuth_DecryptErr_NONE));
+        return Iface_next(&sess->pub.plaintext, msg);
+    }
+    Er_assert(Message_epop(msg, NULL, Message_getLength(msg)));
+    Er_assert(Message_epush32be(msg, CryptoAuth_getState(&sess->pub)));
+    Er_assert(Message_epush32be(msg, e));
+    Er_assert(Message_epush(msg, firstSixteen, 16));
+    Er_assert(Message_epush32h(msg, e));
+    return Iface_next(&sess->pub.plaintext, msg);
 }
 
 struct CryptoAuth_Session* CryptoAuth_newSession(struct CryptoAuth* ca,
                                                  struct Allocator* alloc,
                                                  const uint8_t herPublicKey[32],
                                                  const bool requireAuth,
-                                                 char* displayName)
+                                                 const char* displayName,
+                                                 bool useNoise)
 {
+    Assert_true(!useNoise && "Noise protocol not implemented in old CryptoAuth");
     struct CryptoAuth_pvt* context = Identity_check((struct CryptoAuth_pvt*) ca);
     struct CryptoAuth_Session_pvt* session =
         Allocator_calloc(alloc, sizeof(struct CryptoAuth_Session_pvt), 1);
     Identity_set(session);
+    session->pub.plaintext.send = plaintextMsg;
+    session->pub.ciphertext.send = ciphertextMsg;
     session->context = context;
     session->requireAuth = requireAuth;
-    session->pub.displayName = displayName ? String_new(displayName, alloc) : NULL;
-    session->timeOfLastPacket = Time_currentTimeSeconds(context->eventBase);
+    session->displayName = displayName ? String_new(displayName, alloc) : NULL;
+    session->timeOfLastPacket = Time_currentTimeSeconds();
     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 +1156,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,13 +1181,57 @@ 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;
+    statsOut->noise_proto = false;
+}
+
 // For testing:
-void CryptoAuth_encryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32])
+void CryptoAuth_encryptRndNonce(const uint8_t nonce[24], struct Message* msg, const uint8_t secret[32])
 {
     encryptRndNonce(nonce, msg, secret);
 }
 
-int CryptoAuth_decryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32])
+int CryptoAuth_decryptRndNonce(const uint8_t nonce[24], struct Message* msg, const uint8_t secret[32])
 {
     return decryptRndNonce(nonce, msg, secret);
 }
+

+ 32 - 48
crypto/CryptoAuth.h

@@ -15,7 +15,9 @@
 #ifndef CryptoAuth_H
 #define CryptoAuth_H
 
-#include "benc/StringList.h"
+#include "rust/cjdns_sys/RTypes.h"
+#include "interface/Iface.h"
+#include "benc/String.h"
 #include "crypto/random/Random.h"
 #include "crypto/ReplayProtector.h"
 #include "memory/Allocator.h"
@@ -34,31 +36,13 @@ 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;
+    struct Iface plaintext;
+    struct Iface ciphertext;
 };
 
 /**
@@ -79,7 +63,9 @@ struct CryptoAuth_Session
  * @return 0 if all goes well,
  *         CryptoAuth_addUser_DUPLICATE if the same *password* already exists.
  */
-#define CryptoAuth_addUser_DUPLICATE         -3
+enum CryptoAuth_addUser_Res {
+    CryptoAuth_addUser_DUPLICATE = -3,
+};
 int CryptoAuth_addUser_ipv6(String* password,
                             String* login,
                             uint8_t ipv6[16],
@@ -106,7 +92,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.
@@ -143,9 +129,10 @@ struct CryptoAuth_Session* CryptoAuth_newSession(struct CryptoAuth* ca,
                                                  struct Allocator* alloc,
                                                  const uint8_t herPublicKey[32],
                                                  const bool requireAuth,
-                                                 char* name);
+                                                 const char* name,
+                                                 bool useNoise);
 
-/** @return 0 on success, -1 otherwise. */
+/** @return 0 on success, -1 otherwise. */ // Now only used in unit tests on Rust side
 int CryptoAuth_encrypt(struct CryptoAuth_Session* session, struct Message* msg);
 
 enum CryptoAuth_DecryptErr {
@@ -197,6 +184,7 @@ enum CryptoAuth_DecryptErr {
 
 // returns 0 if everything if ok, otherwise an encryption error.
 // If there is an error, the content of the message MIGHT already be decrypted !
+// Now only used in unit tests on Rust side
 enum CryptoAuth_DecryptErr CryptoAuth_decrypt(struct CryptoAuth_Session* sess, struct Message* msg);
 
 /**
@@ -221,28 +209,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";
@@ -255,6 +229,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

+ 25 - 2
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. */
@@ -118,8 +141,8 @@ struct CryptoAuth_Session_pvt
 //                                    struct CryptoAuth_Wrapper* wrapper,
 //                                    int setupMessage);
 
-int CryptoAuth_decryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32]);
+int CryptoAuth_decryptRndNonce(const uint8_t nonce[24], struct Message* msg, const uint8_t secret[32]);
 
-void CryptoAuth_encryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32]);
+void CryptoAuth_encryptRndNonce(const uint8_t nonce[24], struct Message* msg, const uint8_t secret[32]);
 
 #endif

+ 10 - 10
crypto/Sign.c

@@ -146,10 +146,10 @@ void Sign_signMsg(uint8_t keyPair[64], struct Message* msg, struct Random* rand)
     // hash message + secret number, this is the same as crypto_sign()
     // If there isn't enough space in the message, we abort the process
     Er_assert(Message_epush(msg, &az[32], 32));
-    crypto_hash_sha512(r, msg->bytes, msg->length);
+    crypto_hash_sha512(r, msg->msgbytes, Message_getLength(msg));
 
     // Replace secret number with public key, this is the same as crypto_sign()
-    Bits_memcpy(msg->bytes, &keyPair[32], 32);
+    Bits_memcpy(msg->msgbytes, &keyPair[32], 32);
 
     // Now we scalar multiply the hash of the message + unique secret and push that
     // to the message, nothing different from crypto_sign()
@@ -157,24 +157,24 @@ void Sign_signMsg(uint8_t keyPair[64], struct Message* msg, struct Random* rand)
     ge_scalarmult_base(&R,r);
     // If there isn't enough space in the message, we abort the process
     Er_assert(Message_eshift(msg, 32));
-    ge_p3_tobytes(msg->bytes,&R);
+    ge_p3_tobytes(msg->msgbytes,&R);
 
     // This final step is the same as crypto_sign()
     // Overwrite the public key which the verifier will replace in order to recompute
     // the hash.
-    crypto_hash_sha512(hram, msg->bytes, msg->length);
+    crypto_hash_sha512(hram, msg->msgbytes, Message_getLength(msg));
     sc_reduce(hram);
-    sc_muladd(&msg->bytes[32], hram, az, r);
+    sc_muladd(&msg->msgbytes[32], hram, az, r);
 }
 
 // For verify, we're just using the normal sign_open() function, nothing special here.
 int Sign_verifyMsg(uint8_t publicSigningKey[32], struct Message* msg)
 {
-    if (msg->length < 64) { return -1; }
-    struct Allocator* alloc = Allocator_child(msg->alloc);
-    uint8_t* buff = Allocator_malloc(alloc, msg->length);
-    unsigned long long ml = msg->length;
-    int ret = crypto_sign_ed25519_open(buff, &ml, msg->bytes, msg->length, publicSigningKey);
+    if (Message_getLength(msg) < 64) { return -1; }
+    struct Allocator* alloc = Allocator_child(Message_getAlloc(msg));
+    uint8_t* buff = Allocator_malloc(alloc, Message_getLength(msg));
+    unsigned long long ml = Message_getLength(msg);
+    int ret = crypto_sign_ed25519_open(buff, &ml, msg->msgbytes, Message_getLength(msg), publicSigningKey);
     Allocator_free(alloc);
     if (ret) {
         return -1;

+ 2 - 2
crypto/Sign_admin.c

@@ -68,7 +68,7 @@ static void checkSig(Dict* args, void* vctx, String* txid, struct Allocator* req
         } else if (Sign_publicSigningKeyToCurve25519(curve25519key, publicSigningKey)) {
             Dict_putStringCC(out, "error", "not a valid curve25519 key", requestAlloc);
         } else {
-            struct Address addr;
+            struct Address addr = {0};
             Address_forKey(&addr, curve25519key);
             uint8_t ipv6[40];
             Address_printIp(ipv6, &addr);
@@ -93,7 +93,7 @@ static void sign(Dict* args, void* vctx, String* txid, struct Allocator* request
         Er_assert(Message_epush(msg, msgHash->bytes, msgHash->len));
         Sign_signMsg(ctx->signingKeypair, msg, ctx->rand);
         uint8_t signB64[128];
-        Assert_true(Base32_encode(signB64, 128, msg->bytes, 64) > 0);
+        Assert_true(Base32_encode(signB64, 128, msg->msgbytes, 64) > 0);
         String* sig = String_printf(requestAlloc, "%s_%s", ctx->pubSigningKey, signB64);
         Dict_putStringC(out, "signature", sig, requestAlloc);
         Dict_putStringCC(out, "error", "none", requestAlloc);

+ 28 - 3
crypto/random/Random.c

@@ -21,6 +21,9 @@
 #include "util/Base32.h"
 #include "util/Identity.h"
 #include "util/Endian.h"
+#include "util/Hex.h"
+#include "util/Defined.h"
+#include "util/log/Log.h"
 
 #include <sodium/crypto_hash_sha256.h>
 #include <sodium/crypto_stream_salsa20.h>
@@ -134,7 +137,11 @@ struct Random
     union Random_SeedGen* seedGen;
 
     /** The collector for getting the original permanent random seed from the operating system. */
-    struct RandomSeed* seed;
+    RandomSeed_t* seed;
+
+    struct Allocator* alloc;
+
+    struct Log* log;
 
     Identity
 };
@@ -196,14 +203,30 @@ void Random_bytes(struct Random* rand, uint8_t* location, uint64_t count)
                                   (uint8_t*)&rand->nonce,
                                   (uint8_t*)rand->tempSeed);
         rand->nonce++;
+
+        if (Defined(Log_KEYS)) {
+            struct Allocator* alloc = Allocator_child(rand->alloc);
+            char* buf = Hex_print(location, count, alloc);
+            Log_keys(rand->log, "Random_bytes(%p) -> [%s]", (void*) rand, buf);
+            Allocator_free(alloc);
+        }
         return;
     }
 
+    uint8_t* loc0 = location;
+    uint64_t c0 = count;
+
     for (;;) {
         uintptr_t sz = randomCopy(rand, location, count);
         location += sz;
         count -= sz;
         if (count == 0) {
+            if (Defined(Log_KEYS)) {
+                struct Allocator* alloc = Allocator_child(rand->alloc);
+                char* buf = Hex_print(loc0, c0, alloc);
+                Log_keys(rand->log, "Random_bytes(%p) -> [%s]", (void*) rand, buf);
+                Allocator_free(alloc);
+            }
             return;
         }
         stir(rand);
@@ -228,7 +251,7 @@ void Random_base32(struct Random* rand, uint8_t* output, uint32_t length)
 
 struct Random* Random_newWithSeed(struct Allocator* alloc,
                                   struct Log* logger,
-                                  struct RandomSeed* seed,
+                                  RandomSeed_t* seed,
                                   struct Except* eh)
 {
     union Random_SeedGen* seedGen = Allocator_calloc(alloc, sizeof(union Random_SeedGen), 1);
@@ -241,6 +264,8 @@ struct Random* Random_newWithSeed(struct Allocator* alloc,
     rand->seedGen = seedGen;
     rand->seed = seed;
     rand->nextByte = BUFFSIZE;
+    rand->alloc = alloc;
+    rand->log = logger;
 
     Identity_set(rand);
 
@@ -253,6 +278,6 @@ struct Random* Random_newWithSeed(struct Allocator* alloc,
 
 struct Random* Random_new(struct Allocator* alloc, struct Log* logger, struct Except* eh)
 {
-    struct RandomSeed* rs = SystemRandomSeed_new(NULL, 0, logger, alloc);
+    RandomSeed_t* rs = SystemRandomSeed_new(NULL, 0, logger, alloc);
     return Random_newWithSeed(alloc, logger, rs, eh);
 }

+ 3 - 3
crypto/random/Random.h

@@ -24,9 +24,9 @@ Linker_require("crypto/random/Random.c")
 
 #include <stdint.h>
 
-struct Random;
+typedef struct Random Random_t;
 
-void Random_bytes(struct Random* rand, uint8_t* location, uint64_t count);
+void Random_bytes(Random_t* rand, uint8_t* location, uint64_t count);
 
 /**
  * Get random Base32 text, great for password material.
@@ -103,7 +103,7 @@ static inline uint64_t Random_uint64(struct Random* rand)
 
 struct Random* Random_newWithSeed(struct Allocator* alloc,
                                   struct Log* logger,
-                                  struct RandomSeed* seed,
+                                  RandomSeed_t* seed,
                                   struct Except* eh);
 
 struct Random* Random_new(struct Allocator* alloc, struct Log* logger, struct Except* eh);

+ 3 - 3
crypto/random/seed/BsdKernArndSysctlRandomSeed.c

@@ -24,7 +24,7 @@
 /** Number of times to try each operation. */
 #define MAX_TRIES 10
 
-static int get(struct RandomSeed* randomSeed, uint64_t output[8])
+static int get(RandomSeed_t* randomSeed, uint64_t output[8])
 {
     int mib[] = { CTL_KERN, KERN_ARND };
     Bits_memset(output, 0, 64);
@@ -52,9 +52,9 @@ static int get(struct RandomSeed* randomSeed, uint64_t output[8])
     return Bits_isZero(output, 64) ? -1 : 0;
 }
 
-struct RandomSeed* BsdKernArndSysctlRandomSeed_new(struct Allocator* alloc)
+RandomSeed_t* BsdKernArndSysctlRandomSeed_new(struct Allocator* alloc)
 {
-    return Allocator_clone(alloc, (&(struct RandomSeed) {
+    return Allocator_clone(alloc, (&(RandomSeed_t) {
         .get = get,
         .name = "sysctl(KERN_ARND) (BSD)"
     }));

+ 1 - 1
crypto/random/seed/BsdKernArndSysctlRandomSeed.h

@@ -20,6 +20,6 @@
 #include "util/Linker.h"
 
 Linker_require("crypto/random/seed/BsdKernArndSysctlRandomSeed.c")
-struct RandomSeed* BsdKernArndSysctlRandomSeed_new(struct Allocator* alloc);
+RandomSeed_t* BsdKernArndSysctlRandomSeed_new(struct Allocator* alloc);
 
 #endif

+ 3 - 3
crypto/random/seed/DevUrandomRandomSeed.c

@@ -25,7 +25,7 @@
 /** Number of times to try each operation. */
 #define MAX_TRIES 10
 
-static int get(struct RandomSeed* randomSeed, uint64_t output[8])
+static int get(RandomSeed_t* randomSeed, uint64_t output[8])
 {
     Bits_memset(output, 0, 64);
     int fd = -1;
@@ -58,9 +58,9 @@ static int get(struct RandomSeed* randomSeed, uint64_t output[8])
     return -1;
 }
 
-struct RandomSeed* DevUrandomRandomSeed_new(struct Allocator* alloc)
+RandomSeed_t* DevUrandomRandomSeed_new(struct Allocator* alloc)
 {
-    return Allocator_clone(alloc, (&(struct RandomSeed) {
+    return Allocator_clone(alloc, (&(RandomSeed_t) {
         .get = get,
         .name = "/dev/urandom"
     }));

+ 1 - 1
crypto/random/seed/DevUrandomRandomSeed.h

@@ -20,6 +20,6 @@
 #include "util/Linker.h"
 
 Linker_require("crypto/random/seed/DevUrandomRandomSeed.c")
-struct RandomSeed* DevUrandomRandomSeed_new(struct Allocator* alloc);
+RandomSeed_t* DevUrandomRandomSeed_new(struct Allocator* alloc);
 
 #endif

+ 3 - 3
crypto/random/seed/GetEntropyRandomSeed.c

@@ -53,7 +53,7 @@ static int getEntropy(void *buf, size_t buflen)
 }
 #endif
 
-static int get(struct RandomSeed* randomSeed, uint64_t output[8])
+static int get(RandomSeed_t* randomSeed, uint64_t output[8])
 {
     if (getEntropy(output, 64) < 0) {
         return -1;
@@ -62,9 +62,9 @@ static int get(struct RandomSeed* randomSeed, uint64_t output[8])
     }
 }
 
-struct RandomSeed* GetEntropyRandomSeed_new(struct Allocator* alloc)
+RandomSeed_t* GetEntropyRandomSeed_new(struct Allocator* alloc)
 {
-    return Allocator_clone(alloc, (&(struct RandomSeed) {
+    return Allocator_clone(alloc, (&(RandomSeed_t) {
         .get = get,
         .name = "getentropy(2)"
     }));

+ 1 - 1
crypto/random/seed/GetEntropyRandomSeed.h

@@ -20,6 +20,6 @@
 #include "util/Linker.h"
 
 Linker_require("crypto/random/seed/GetEntropyRandomSeed.c")
-struct RandomSeed* GetEntropyRandomSeed_new(struct Allocator* alloc);
+RandomSeed_t* GetEntropyRandomSeed_new(struct Allocator* alloc);
 
 #endif

+ 3 - 3
crypto/random/seed/LinuxRandomUuidSysctlRandomSeed.c

@@ -38,7 +38,7 @@ static int getUUID(uint64_t output[2])
 }
 #endif
 
-static int get(struct RandomSeed* randomSeed, uint64_t output[8])
+static int get(RandomSeed_t* randomSeed, uint64_t output[8])
 {
 
 #ifdef SYS_getrandom
@@ -59,9 +59,9 @@ static int get(struct RandomSeed* randomSeed, uint64_t output[8])
 #endif
 }
 
-struct RandomSeed* LinuxRandomUuidSysctlRandomSeed_new(struct Allocator* alloc)
+RandomSeed_t* LinuxRandomUuidSysctlRandomSeed_new(struct Allocator* alloc)
 {
-    return Allocator_clone(alloc, (&(struct RandomSeed) {
+    return Allocator_clone(alloc, (&(RandomSeed_t) {
         .get = get,
         .name = "sysctl(RANDOM_UUID) (Linux)"
     }));

+ 1 - 1
crypto/random/seed/LinuxRandomUuidSysctlRandomSeed.h

@@ -20,6 +20,6 @@
 #include "util/Linker.h"
 
 Linker_require("crypto/random/seed/LinuxRandomUuidSysctlRandomSeed.c")
-struct RandomSeed* LinuxRandomUuidSysctlRandomSeed_new(struct Allocator* alloc);
+RandomSeed_t* LinuxRandomUuidSysctlRandomSeed_new(struct Allocator* alloc);
 
 #endif

+ 3 - 3
crypto/random/seed/ProcSysKernelRandomUuidRandomSeed.c

@@ -82,7 +82,7 @@ static int getUUID(uint64_t output[2])
     return 0;
 }
 
-static int get(struct RandomSeed* randomSeed, uint64_t output[8])
+static int get(RandomSeed_t* randomSeed, uint64_t output[8])
 {
     if (getUUID(output) || getUUID(output+2) || getUUID(output+4) || getUUID(output+6)) {
         return -1;
@@ -90,9 +90,9 @@ static int get(struct RandomSeed* randomSeed, uint64_t output[8])
     return 0;
 }
 
-struct RandomSeed* ProcSysKernelRandomUuidRandomSeed_new(struct Allocator* alloc)
+RandomSeed_t* ProcSysKernelRandomUuidRandomSeed_new(struct Allocator* alloc)
 {
-    return Allocator_clone(alloc, (&(struct RandomSeed) {
+    return Allocator_clone(alloc, (&(RandomSeed_t) {
         .get = get,
         .name = "/proc/sys/kernel/random/uuid (Linux)"
     }));

+ 1 - 1
crypto/random/seed/ProcSysKernelRandomUuidRandomSeed.h

@@ -20,6 +20,6 @@
 #include "util/Linker.h"
 
 Linker_require("crypto/random/seed/ProcSysKernelRandomUuidRandomSeed.c")
-struct RandomSeed* ProcSysKernelRandomUuidRandomSeed_new(struct Allocator* alloc);
+RandomSeed_t* ProcSysKernelRandomUuidRandomSeed_new(struct Allocator* alloc);
 
 #endif

+ 7 - 7
crypto/random/seed/RandomSeed.c

@@ -21,8 +21,8 @@
 
 struct RandomSeed_pvt
 {
-    struct RandomSeed pub;
-    struct RandomSeed** rsList;
+    RandomSeed_t pub;
+    RandomSeed_t** rsList;
     int rsCount;
     struct Log* logger;
     Identity
@@ -36,7 +36,7 @@ struct RandomSeed_Buffer
 #define RandomSeed_Buffer_SIZE 128
 Assert_compileTime(sizeof(struct RandomSeed_Buffer) == RandomSeed_Buffer_SIZE);
 
-static int get(struct RandomSeed* rs, uint64_t buffer[8])
+static int get(RandomSeed_t* rs, uint64_t buffer[8])
 {
     struct RandomSeed_pvt* ctx = Identity_check((struct RandomSeed_pvt*) rs);
     Log_info(ctx->logger, "Attempting to seed random number generator");
@@ -69,20 +69,20 @@ static int get(struct RandomSeed* rs, uint64_t buffer[8])
     }
 }
 
-int RandomSeed_get(struct RandomSeed* rs, uint64_t buffer[8])
+int RandomSeed_get(RandomSeed_t* rs, uint64_t buffer[8])
 {
     return rs->get(rs, buffer);
 }
 
-struct RandomSeed* RandomSeed_new(RandomSeed_Provider* providers,
+RandomSeed_t* RandomSeed_new(RandomSeed_Provider* providers,
                                   int providerCount,
                                   struct Log* logger,
                                   struct Allocator* alloc)
 {
-    struct RandomSeed** rsList = Allocator_calloc(alloc, sizeof(struct RandomSeed), providerCount);
+    RandomSeed_t** rsList = Allocator_calloc(alloc, sizeof(RandomSeed_t), providerCount);
     int i = 0;
     for (int j = 0; j < providerCount; j++) {
-        struct RandomSeed* rs = providers[j](alloc);
+        RandomSeed_t* rs = providers[j](alloc);
         if (rs) {
             rsList[i++] = rs;
         }

+ 6 - 6
crypto/random/seed/RandomSeed.h

@@ -22,12 +22,12 @@ Linker_require("crypto/random/seed/RandomSeed.c")
 
 #include <stdint.h>
 
-struct RandomSeed;
+typedef struct RandomSeed_s RandomSeed_t;
 
-typedef struct RandomSeed* (* RandomSeed_Provider)(struct Allocator* alloc);
-typedef int (* RandomSeed_Get)(struct RandomSeed* context, uint64_t buff[8]);
+typedef RandomSeed_t* (* RandomSeed_Provider)(struct Allocator* alloc);
+typedef int (* RandomSeed_Get)(RandomSeed_t* context, uint64_t buff[8]);
 
-struct RandomSeed
+struct RandomSeed_s
 {
     /**
      * Get some random numbers.
@@ -42,11 +42,11 @@ struct RandomSeed
     const char* name;
 };
 
-struct RandomSeed* RandomSeed_new(RandomSeed_Provider* providers,
+RandomSeed_t* RandomSeed_new(RandomSeed_Provider* providers,
                                   int providerCount,
                                   struct Log* logger,
                                   struct Allocator* alloc);
 
-int RandomSeed_get(struct RandomSeed* rs, uint64_t buffer[8]);
+int RandomSeed_get(RandomSeed_t* rs, uint64_t buffer[8]);
 
 #endif

+ 3 - 3
crypto/random/seed/RtlGenRandomSeed.c

@@ -19,7 +19,7 @@
 #include <windows.h>
 #include <ntsecapi.h>
 
-static int get(struct RandomSeed* rand, uint64_t buff[8])
+static int get(RandomSeed_t* rand, uint64_t buff[8])
 {
     Bits_memset(buff, 0, 64);
     int ret = RtlGenRandom(buff, 64);
@@ -29,9 +29,9 @@ static int get(struct RandomSeed* rand, uint64_t buff[8])
     return 0;
 }
 
-struct RandomSeed* RtlGenRandomSeed_new(struct Allocator* alloc)
+RandomSeed_t* RtlGenRandomSeed_new(struct Allocator* alloc)
 {
-    return Allocator_clone(alloc, (&(struct RandomSeed) {
+    return Allocator_clone(alloc, (&(RandomSeed_t) {
         .get = get,
         .name = "RtlGenRandom() (Windows)"
     }));

+ 1 - 1
crypto/random/seed/RtlGenRandomSeed.h

@@ -20,6 +20,6 @@
 #include "util/Linker.h"
 
 Linker_require("crypto/random/seed/RtlGenRandomSeed.c")
-struct RandomSeed* RtlGenRandomSeed_new(struct Allocator* alloc);
+RandomSeed_t* RtlGenRandomSeed_new(struct Allocator* alloc);
 
 #endif

+ 1 - 1
crypto/random/seed/SystemRandomSeed.c

@@ -50,7 +50,7 @@ Js({ this.RandomSeedProvider_providers = []; })
 static RandomSeed_Provider PROVIDERS[] = { RandomSeedProvider_list() };
 #define PROVIDERS_COUNT ((int)(sizeof(PROVIDERS) / sizeof(RandomSeed_Provider)))
 
-struct RandomSeed* SystemRandomSeed_new(RandomSeed_Provider* additionalProviders,
+RandomSeed_t* SystemRandomSeed_new(RandomSeed_Provider* additionalProviders,
                                         int additionalProviderCount,
                                         struct Log* logger,
                                         struct Allocator* alloc)

+ 1 - 1
crypto/random/seed/SystemRandomSeed.h

@@ -24,7 +24,7 @@ Linker_require("crypto/random/seed/SystemRandomSeed.c")
  * Create a new randomseed with the default system providers as well as optionally more providers
  * additionalProviders is a null terminalted list.
  */
-struct RandomSeed* SystemRandomSeed_new(RandomSeed_Provider* additionalProviders,
+RandomSeed_t* SystemRandomSeed_new(RandomSeed_Provider* additionalProviders,
                                         int additionalProviderCount,
                                         struct Log* logger,
                                         struct Allocator* alloc);

+ 3 - 3
crypto/random/test/DeterminentRandomSeed.c

@@ -21,12 +21,12 @@
  */
 
  struct DeterminentRandomSeed {
-     struct RandomSeed rs;
+     RandomSeed_t rs;
      uint8_t buff[64];
      Identity
  };
 
-static int get(struct RandomSeed* rand, uint64_t buff[8])
+static int get(RandomSeed_t* rand, uint64_t buff[8])
 {
     // chosen by fair dice roll, guaranteed random.
     struct DeterminentRandomSeed* drs = Identity_check((struct DeterminentRandomSeed*) rand);
@@ -34,7 +34,7 @@ static int get(struct RandomSeed* rand, uint64_t buff[8])
     return 0;
 }
 
-struct RandomSeed* DeterminentRandomSeed_new(struct Allocator* alloc, uint8_t buff[64])
+RandomSeed_t* DeterminentRandomSeed_new(struct Allocator* alloc, uint8_t buff[64])
 {
     struct DeterminentRandomSeed* drs = Allocator_clone(alloc, (&(struct DeterminentRandomSeed) {
         .rs = {

+ 1 - 1
crypto/random/test/DeterminentRandomSeed.h

@@ -20,6 +20,6 @@
 #include "util/Linker.h"
 Linker_require("crypto/random/test/DeterminentRandomSeed.c")
 
-struct RandomSeed* DeterminentRandomSeed_new(struct Allocator* alloc, uint8_t buff[64]);
+RandomSeed_t* DeterminentRandomSeed_new(struct Allocator* alloc, uint8_t buff[64]);
 
 #endif

+ 1 - 1
crypto/random/test/Random_test.c

@@ -90,7 +90,7 @@ static void test179(struct Allocator* alloc, struct Log* logger)
 int main()
 {
     struct Allocator* alloc = MallocAllocator_new(1<<20);
-    struct RandomSeed* seed = DeterminentRandomSeed_new(alloc, NULL);
+    RandomSeed_t* seed = DeterminentRandomSeed_new(alloc, NULL);
     struct Writer* w = FileWriter_new(stdout, alloc);
     struct Log* logger = WriterLog_new(w, alloc);
     struct Random* rand = Random_newWithSeed(alloc, logger, seed, NULL);

+ 102 - 43
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,7 @@
 #include "crypto/random/test/DeterminentRandomSeed.h"
 #include "crypto/random/Random.h"
 #include "crypto/AddressCalc.h"
-#include "test/FuzzTest.h"
+#include "crypto/CryptoAuth.h"
 
 struct DelayedMsg {
     struct Message* msg;
@@ -35,11 +36,18 @@ struct DelayedMsg {
     int sendAfter;
 };
 
+struct Context;
+
 struct Node {
-    struct CryptoAuth* ca;
-    struct CryptoAuth_Session* session;
+    TestCa_t* ca;
+    TestCa_Session_t* session;
+    struct Iface plaintext;
+    struct Iface ciphertext;
     struct DelayedMsg* delayedMsgs;
     int sendCounter;
+    uint8_t pubKey[32];
+    struct Context* ctx;
+    Identity
 };
 
 struct Context {
@@ -78,7 +86,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);
 }
 
 /**
@@ -108,8 +116,8 @@ static bool isMutableBit(int bitNum)
 
 static void flipBit(struct Message* msg, uint32_t bitNum)
 {
-    Assert_true(msg->length * 8 > (int)bitNum);
-    msg->bytes[bitNum / 8] ^= 128 >> (bitNum % 8);
+    Assert_true(Message_getLength(msg) * 8 > (int)bitNum);
+    msg->msgbytes[bitNum / 8] ^= 128 >> (bitNum % 8);
 }
 
 static void flipMutableBit(struct Context* ctx, struct Node* from, struct Message* msg)
@@ -126,7 +134,7 @@ static void flipImmutableBit(struct Context* ctx, struct Node* from, struct Mess
 {
     uint32_t bitNum;
     do {
-        bitNum = Random_uint16(ctx->rand) % (msg->length * 8);
+        bitNum = Random_uint16(ctx->rand) % (Message_getLength(msg) * 8);
     } while (isMutableBit(bitNum));
     logNode(ctx, from, "FLIPPING IMMUTABLE BIT %u", bitNum);
     flipBit(msg, bitNum);
@@ -166,7 +174,7 @@ static void delay(struct Context* ctx, struct Node* from, struct Message* msg, i
     logNode(ctx, from, "DELAY %d packets (ptr:%p)", afterMsgs, (void*)msg);
     struct Allocator* alloc = Allocator_child(ctx->alloc);
     struct DelayedMsg* delayed = Allocator_calloc(alloc, sizeof(struct DelayedMsg), 1);
-    Allocator_adopt(alloc, msg->alloc);
+    Allocator_adopt(alloc, Message_getAlloc(msg));
     delayed->msg = msg;
     delayed->sendAfter = from->sendCounter + afterMsgs;
     delayed->alloc = alloc;
@@ -209,23 +217,10 @@ static void sendFrom(struct Context* ctx, struct Node* from, struct Message* msg
         flippedImmutable = true;
     }
 
-    if (!CryptoAuth_decrypt(to->session, msg)) {
-        Assert_true(!flippedImmutable);
-        Assert_true(msg->length == 4 && !Bits_memcmp(msg->bytes, "hey", 4));
-        if (to == &ctx->nodeB) {
-            // 1/10 chance the node decides not to reply.
-            if (maybe(ctx, 10)) {
-                return;
-            }
-            Assert_true(!CryptoAuth_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)
-        {
-            ctx->successMessageCount++;
-        }
-    }
+    Er_assert(Message_epushAd(msg, &flippedImmutable, sizeof flippedImmutable));
+    Er_assert(Message_epush(msg, NULL, 16)); // peer ipv6
+
+    Iface_send(&to->ciphertext, msg); // --> afterDecrypt (hopefully)
 }
 
 static bool sendQueued(struct Context* ctx, struct Node* fromNode)
@@ -259,56 +254,120 @@ 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));
-        sendFrom(ctx, &ctx->nodeA, msg);
+        Iface_send(&ctx->nodeA.plaintext, msg);
+        //Assert_true(!TestCa_encrypt(ctx->nodeA.session, msg));
+        //sendFrom(ctx, &ctx->nodeA, msg);
         Allocator_free(alloc);
     }
 
     Assert_failure("Nodes could not sync");
 }
 
-void* CJDNS_FUZZ_INIT(struct Allocator* alloc, struct Random* rand)
+static Iface_DEFUN afterEncrypt(struct Message* msg, struct Iface* iface)
+{
+    struct Node* n = Identity_containerOf(iface, struct Node, ciphertext);
+    sendFrom(n->ctx, n, msg);
+    return NULL;
+}
+
+static Iface_DEFUN afterDecrypt(struct Message* msg, struct Iface* iface)
+{
+    bool flippedImmutable = false;
+    Er_assert(Message_epopAd(msg, &flippedImmutable, sizeof flippedImmutable));
+
+    struct Node* to = Identity_containerOf(iface, struct Node, plaintext);
+
+    enum CryptoAuth_DecryptErr e = Er_assert(Message_epop32h(msg));
+    if (!e) {
+        Assert_true(!flippedImmutable);
+        Assert_true(Message_getLength(msg) == 4 && !Bits_memcmp(msg->msgbytes, "hey", 4));
+        if (to == &to->ctx->nodeB) {
+            // 1/10 chance the node decides not to reply.
+            if (maybe(to->ctx, 10)) {
+                return NULL;
+            }
+            //Assert_true(!TestCa_encrypt(to->session, msg));
+            to->sendCounter++;
+            Iface_send(&to->plaintext, msg);
+            //sendFrom(ctx, to, msg);
+        } else if (TestCa_getState(to->ctx->nodeA.session) == RTypes_CryptoAuth_State_t_Established &&
+            TestCa_getState(to->ctx->nodeB.session) == RTypes_CryptoAuth_State_t_Established)
+        {
+            to->ctx->successMessageCount++;
+        }
+    }
+    return NULL;
+}
+
+#define PRIVATEKEY_A \
+    Constant_stringForHex("53ff22b2eb94ce8c5f1852c0f557eb901f067e5273d541e0a21e143c20dff9da")
+#define PRIVATEKEY_B \
+    Constant_stringForHex("b71c4f43e3d4b1879b5065d44a1cb43eaf07ddba96de6a72ca761c4ef4bd2988")
+
+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);
+    Identity_set(&ctx->nodeA);
+    Identity_set(&ctx->nodeB);
     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");
+
+    uint8_t buf[64];
+    Random_bytes(rand, buf, 64);
+    Random_t* r0 = Random_newWithSeed(alloc, NULL, DeterminentRandomSeed_new(alloc, buf), NULL);
+    Random_t* r1 = Random_newWithSeed(alloc, NULL, DeterminentRandomSeed_new(alloc, buf), NULL);
+
+    ctx->nodeA.ca = TestCa_new(alloc, PRIVATEKEY_A, base, NULL, r0, r1, cfg);
+    ctx->nodeB.ca = TestCa_new(alloc, PRIVATEKEY_B, base, NULL, r0, r1, cfg);
+    TestCa_getPubKey(ctx->nodeA.ca, ctx->nodeA.pubKey);
+    TestCa_getPubKey(ctx->nodeB.ca, ctx->nodeB.pubKey);
+
+    ctx->nodeA.ctx = ctx;
+    ctx->nodeA.ciphertext.send = afterEncrypt;
+    ctx->nodeA.plaintext.send = afterDecrypt;
+    ctx->nodeA.session = TestCa_newSession(
+        ctx->nodeA.ca, alloc, ctx->nodeB.pubKey, false, "nodeA", true);
+    Iface_plumb(&ctx->nodeA.ciphertext, &ctx->nodeA.session->ciphertext);
+    Iface_plumb(&ctx->nodeA.plaintext, &ctx->nodeA.session->plaintext);
+
+    ctx->nodeB.ctx = ctx;
+    ctx->nodeB.ciphertext.send = afterEncrypt;
+    ctx->nodeB.plaintext.send = afterDecrypt;
+    ctx->nodeB.session = TestCa_newSession(
+        ctx->nodeB.ca, alloc, ctx->nodeA.pubKey, false, "nodeB", true);
+    Iface_plumb(&ctx->nodeB.ciphertext, &ctx->nodeB.session->ciphertext);
+    Iface_plumb(&ctx->nodeB.plaintext, &ctx->nodeB.session->plaintext);
     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);
 
     // This is not ideal, but this test was already written before AFL.
-    struct RandomSeed* rs = DeterminentRandomSeed_new(ctx->alloc, fuzz->bytes);
+    RandomSeed_t* rs = DeterminentRandomSeed_new(ctx->alloc, fuzz->msgbytes);
     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

+ 26 - 0
crypto/test/CryptoAuthFuzz_noise_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_NOISE);
+}
+void CJDNS_FUZZ_MAIN(void* vctx, struct Message* fuzz)
+{
+    // TODO(cjd): DISABLED TEST 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

+ 26 - 0
crypto/test/CryptoAuthFuzz_oldnew_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_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

+ 57 - 0
crypto/test/CryptoAuth_randnonce_test.c

@@ -0,0 +1,57 @@
+/* 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 = Message_foreign(44, buff);
+    Er_assert(Message_epop(&m, NULL, 44));
+    Er_assert(Message_epush(&m, HELLOWORLDLOWER, CString_strlen(HELLOWORLDLOWER)+1));
+
+    CryptoAuth_encryptRndNonce(nonce, &m, secret);
+
+    uint8_t* expected = (uint8_t*) "1391ac5d03ba9f7099bffbb6e6c69d67ae5bd79391a5b94399b293dc";
+    uint8_t output[57];
+    Hex_encode(output, 57, m.msgbytes, Message_getLength(&m));
+
+    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(Message_getLength(&m) == HELLOWORLDLEN
+        && !Bits_memcmp(m.msgbytes, HELLOWORLDLOWER, Message_getLength(&m)));
+}
+
+int main()
+{
+    encryptRndNonceTest();
+    return 0;
+}

+ 185 - 99
crypto/test/CryptoAuth_test.c

@@ -13,6 +13,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 #include "crypto/random/Random.h"
+#include "crypto/Ca.h"
 #include "crypto/CryptoAuth.h"
 #include "benc/String.h"
 #include "memory/MallocAllocator.h"
@@ -23,6 +24,9 @@
 #include "util/Endian.h"
 #include "util/log/FileWriterLog.h"
 #include "wire/CryptoHeader.h"
+#include "crypto/test/TestCa.h"
+#include "crypto/random/test/DeterminentRandomSeed.h"
+#include "util/CString.h"
 
 #define PRIVATEKEY_A \
     Constant_stringForHex("53ff22b2eb94ce8c5f1852c0f557eb901f067e5273d541e0a21e143c20dff9da")
@@ -36,103 +40,171 @@
 
 #define USEROBJ "This represents a user"
 
-struct Context
+struct Node
 {
-    struct CryptoAuth* ca1;
-    struct CryptoAuth_Session* sess1;
+    TestCa_t* ca;
+    TestCa_Session_t* sess;
+    struct Iface plaintext;
+    struct Iface ciphertext;
+    const char* expectPlaintext;
+    enum CryptoAuth_DecryptErr expectErr;
+    struct Log* log;
+    Identity
+};
 
-    struct CryptoAuth* ca2;
-    struct CryptoAuth_Session* sess2;
+struct Context
+{
+    struct Node node1;
+    struct Node node2;
 
     struct Allocator* alloc;
     struct Log* log;
-    struct Random* rand;
     struct EventBase* base;
+    Identity
 };
 
+static struct Random* evilRandom(struct Allocator* alloc, struct Log* logger, const char* seed)
+{
+    uint8_t buf[64] = {0};
+    Assert_true(CString_strlen(seed) < 60);
+    CString_strcpy(buf, seed);
+    RandomSeed_t* evilSeed = DeterminentRandomSeed_new(alloc, buf);
+    return Random_newWithSeed(alloc, logger, evilSeed, NULL);
+}
+
+static Iface_DEFUN afterDecrypt(struct Message* msg, struct Iface* if1)
+{
+    struct Node* n = Identity_containerOf(if1, struct Node, plaintext);
+    Log_debug(n->log, "Got message from afterDecrypt");
+    enum CryptoAuth_DecryptErr e = Er_assert(Message_epop32h(msg));
+    if (e != n->expectErr) {
+        Assert_failure("expected decrypt error [%d], got [%d]\n", n->expectErr, e);
+    }
+    n->expectErr = CryptoAuth_DecryptErr_NONE;
+    if (!n->expectPlaintext) {
+        if (e) {
+            return NULL;
+        }
+        Assert_failure("expected <NULL>, got [%s](%d)\n", msg->msgbytes, Message_getLength(msg));
+    }
+    if ((int)CString_strlen(n->expectPlaintext) != Message_getLength(msg) ||
+        CString_strncmp(msg->msgbytes, n->expectPlaintext, Message_getLength(msg)))
+    {
+        Assert_failure("expected [%s](%d), got [%s](%d)\n",
+            n->expectPlaintext, (int)CString_strlen(n->expectPlaintext), msg->msgbytes, Message_getLength(msg));
+    }
+    n->expectPlaintext = NULL;
+    return NULL;
+}
+
+static Iface_DEFUN afterEncrypt(struct Message* msg, struct Iface* if1)
+{
+    return NULL;
+}
+
 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);
+    Identity_set(ctx);
+    Identity_set(&ctx->node1);
+    Identity_set(&ctx->node2);
     ctx->alloc = alloc;
+    ctx->node1.plaintext.send = afterDecrypt;
+    ctx->node2.plaintext.send = afterDecrypt;
+    ctx->node1.ciphertext.send = afterEncrypt;
+    ctx->node2.ciphertext.send = afterEncrypt;
     struct Log* logger = ctx->log = FileWriterLog_new(stdout, alloc);
-    struct Random* rand = ctx->rand = Random_new(alloc, logger, NULL);
+    struct Random* randA = evilRandom(alloc, logger, "ALPHA");
+    struct Random* randB = evilRandom(alloc, logger, "ALPHA");
+    struct Random* randC = evilRandom(alloc, logger, "BRAVO");
+    struct Random* randD = evilRandom(alloc, logger, "BRAVO");
     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->node1.log = logger;
+    ctx->node2.log = logger;
+
+    ctx->node1.ca = TestCa_new(alloc, privateKeyA, base, logger, randA, randB, cfg);
+    ctx->node1.sess = TestCa_newSession(ctx->node1.ca, alloc, publicKeyB, false, "cif1", true);
 
-    ctx->ca2 = CryptoAuth_new(alloc, privateKeyB, base, logger, rand);
+    ctx->node2.ca = TestCa_new(alloc, privateKeyB, base, logger, randC, randD, 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->node1.sess);
+        TestCa_addUser_ipv6(passStr, String_new(USEROBJ, alloc), NULL, ctx->node2.ca);
     }
-    ctx->sess2 = CryptoAuth_newSession(ctx->ca2, alloc, publicKeyA, false, "cif2");
+    ctx->node2.sess = TestCa_newSession(ctx->node2.ca, alloc, publicKeyA, false, "cif2", true);
+
+    Iface_plumb(&ctx->node1.sess->plaintext, &ctx->node1.plaintext);
+    Iface_plumb(&ctx->node1.sess->ciphertext, &ctx->node1.ciphertext);
+
+    Iface_plumb(&ctx->node2.sess->plaintext, &ctx->node2.plaintext);
+    Iface_plumb(&ctx->node2.sess->ciphertext, &ctx->node2.ciphertext);
 
     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,
+                                  struct Node* n,
                                   const char* x)
 {
     struct Allocator* alloc = Allocator_child(ctx->alloc);
     int len = (((CString_strlen(x)+1) / 8) + 1) * 8;
-    struct Message* msg = Message_new(len, CryptoHeader_SIZE, alloc);
-    CString_strcpy(msg->bytes, x);
-    msg->length = CString_strlen(x);
-    msg->bytes[msg->length] = 0;
-    Assert_true(!CryptoAuth_encrypt(encryptWith, msg));
-    Assert_true(msg->length > ((int)CString_strlen(x) + 4));
+    struct Message* msg = Message_new(len, CryptoHeader_SIZE + 32, alloc);
+    CString_strcpy(msg->msgbytes, x);
+    Er_assert(Message_truncate(msg, CString_strlen(x)));
+    //msg->bytes[Message_getLength(msg)] = 0;
+    struct RTypes_Error_t* e = Iface_send(&n->plaintext, msg);
+    if (e) {
+        printf("%s\n", Rffi_printError(e, ctx->alloc));
+        Assert_failure("error was not null");
+    }
+    Assert_true(Message_getLength(msg) > ((int)CString_strlen(x) + 4));
     return msg;
 }
 
-static void decryptMsg(struct Context* ctx,
-                       struct Message* msg,
-                       struct CryptoAuth_Session* decryptWith,
-                       const char* x)
+static struct Message* decryptMsg(struct Context* ctx,
+                                  struct Message* msg,
+                                  struct Node* n,
+                                  const char* expectResult,
+                                  enum CryptoAuth_DecryptErr expectErr)
 {
-    if (!x) {
-        // x is null implying it is expected to fail.
-        Assert_true(CryptoAuth_decrypt(decryptWith, msg));
-    } else {
-        Assert_true(!CryptoAuth_decrypt(decryptWith, msg));
-        if ((int)CString_strlen(x) != msg->length ||
-            CString_strncmp(msg->bytes, x, msg->length))
-        {
-            Assert_failure("expected [%s](%d), got [%s](%d)\n",
-                x, (int)CString_strlen(x), msg->bytes, msg->length);
-        }
-    }
+    Assert_true(!n->expectPlaintext && !n->expectErr);
+    n->expectPlaintext = expectResult;
+    n->expectErr = expectErr;
+    Er_assert(Message_epush(msg, NULL, 16)); // peer ipv6
+    Iface_send(&n->ciphertext, msg);
+    Assert_true(!n->expectPlaintext && !n->expectErr);
+    return msg;
 }
 
 static void sendToIf1(struct Context* ctx, const char* x)
 {
-    struct Message* msg = encryptMsg(ctx, ctx->sess2, x);
-    decryptMsg(ctx, msg, ctx->sess1, x);
-    Allocator_free(msg->alloc);
+    struct Message* msg = encryptMsg(ctx, &ctx->node2, x);
+    decryptMsg(ctx, msg, &ctx->node1, x, CryptoAuth_DecryptErr_NONE);
+    Allocator_free(Message_getAlloc(msg));
 }
 
 static void sendToIf2(struct Context* ctx, const char* x)
 {
-    struct Message* msg = encryptMsg(ctx, ctx->sess1, x);
-    decryptMsg(ctx, msg, ctx->sess2, x);
-    Allocator_free(msg->alloc);
+    struct Message* msg = encryptMsg(ctx, &ctx->node1, x);
+    decryptMsg(ctx, msg, &ctx->node2, x, CryptoAuth_DecryptErr_NONE);
+    Allocator_free(Message_getAlloc(msg));
 }
 
-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 +212,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 +223,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 +234,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 +253,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,32 +264,32 @@ 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");
 
-    struct Message* msg = encryptMsg(ctx, ctx->sess2, "hello replay key");
+    struct Message* msg = encryptMsg(ctx, &ctx->node2, "hello replay key");
     struct Message* toReplay = Message_clone(msg, ctx->alloc);
-    decryptMsg(ctx, msg, ctx->sess1, "hello replay key");
+    decryptMsg(ctx, msg, &ctx->node1, "hello replay key", CryptoAuth_DecryptErr_NONE);
 
     if (scenario == 1) {
         // the packet is failed because we know it's a dupe from the temp key.
-        decryptMsg(ctx, toReplay, ctx->sess1, NULL);
+        decryptMsg(ctx, toReplay, &ctx->node1, NULL, CryptoAuth_DecryptErr_INVALID_PACKET);
     }
 
     sendToIf2(ctx, "first traffic packet");
 
     if (scenario == 2) {
-        decryptMsg(ctx, toReplay, ctx->sess1, NULL);
+        decryptMsg(ctx, toReplay, &ctx->node1, NULL, CryptoAuth_DecryptErr_INVALID_PACKET);
     }
 
     sendToIf1(ctx, "second traffic packet");
 
     if (scenario == 3) {
         // If we replay at this stage, the packet is dropped as a stray key
-        decryptMsg(ctx, toReplay, ctx->sess1, NULL);
+        decryptMsg(ctx, toReplay, &ctx->node1, NULL, CryptoAuth_DecryptErr_KEY_PKT_ESTABLISHED_SESSION);
     }
 
     Allocator_free(ctx->alloc);
@@ -227,16 +300,20 @@ 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->node1.ca, pk1);
+    uint8_t hpk2[32];
+    TestCa_getHerPubKey(ctx->node2.sess, hpk2);
+    Assert_true(!Bits_memcmp(pk1, hpk2, 32));
 
-    struct Message* hello2 = encryptMsg(ctx, ctx->sess2, "hello2");
-    struct Message* hello1 = encryptMsg(ctx, ctx->sess1, "hello1");
+    struct Message* hello2 = encryptMsg(ctx, &ctx->node2, "hello2");
+    struct Message* hello1 = encryptMsg(ctx, &ctx->node1, "hello1");
 
-    decryptMsg(ctx, hello2, ctx->sess1, "hello2");
-    decryptMsg(ctx, hello1, ctx->sess2, "hello1");
+    decryptMsg(ctx, hello2, &ctx->node1, "hello2", 0);
+    decryptMsg(ctx, hello1, &ctx->node2, "hello1", 0);
 
     sendToIf2(ctx, "hello world");
     sendToIf1(ctx, "hello cjdns");
@@ -246,77 +323,86 @@ 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->node1.sess) == CryptoAuth_State_ESTABLISHED);
+    Assert_true(TestCa_getState(ctx->node2.sess) == CryptoAuth_State_ESTABLISHED);
 
-    CryptoAuth_reset(ctx->sess1);
+    TestCa_reset(ctx->node1.sess);
 
     // 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);
-    decryptMsg(ctx, encryptMsg(ctx, ctx->sess2, "lost"), ctx->sess1, NULL);
+    decryptMsg(ctx, encryptMsg(ctx, &ctx->node2, "will be lost"), &ctx->node1, NULL,
+        CryptoAuth_DecryptErr_NO_SESSION);
+    decryptMsg(ctx, encryptMsg(ctx, &ctx->node2, "lost"), &ctx->node1, NULL,
+        CryptoAuth_DecryptErr_NO_SESSION);
 
     // This is because we want to prevent replay attacks from tearing down a session.
-    decryptMsg(ctx, encryptMsg(ctx, ctx->sess1, "hello"), ctx->sess2, "hello");
+    decryptMsg(ctx, encryptMsg(ctx, &ctx->node1, "hello"), &ctx->node2, "hello", 0);
 
     sendToIf1(ctx, "hello again");
     sendToIf2(ctx, "hai");
     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->node1.sess) == CryptoAuth_State_ESTABLISHED);
+    Assert_true(TestCa_getState(ctx->node2.sess) == 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");
-    struct Message* key2 = encryptMsg(ctx, ctx->sess2, "key packet 2");
+    struct Message* key2 = encryptMsg(ctx, &ctx->node2, "key packet 2");
 
     if (scenario == 1) {
         sendToIf1(ctx, "key packet 3");
-        decryptMsg(ctx, key2, ctx->sess1, "key packet 2");
+        decryptMsg(ctx, key2, &ctx->node1, "key packet 2", 0);
     } else if (scenario == 2) {
         sendToIf2(ctx, "initial data packet");
-        decryptMsg(ctx, key2, ctx->sess1, "key packet 2");
+        decryptMsg(ctx, key2, &ctx->node1, "key packet 2", 0);
         sendToIf1(ctx, "second data packet");
         sendToIf2(ctx, "third data packet");
     } else if (scenario == 3) {
         sendToIf2(ctx, "initial data packet");
         sendToIf1(ctx, "second data packet");
-        decryptMsg(ctx, key2, ctx->sess1, NULL);
+        decryptMsg(ctx, key2, &ctx->node1, NULL, CryptoAuth_DecryptErr_KEY_PKT_ESTABLISHED_SESSION);
     }
     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); // TODO(cjd): re-enable this
     return 0;
-}
+}

+ 81 - 80
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,80 +37,67 @@
 #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);
+    RandomSeed_t* evilSeed = DeterminentRandomSeed_new(alloc, NULL);
     return Random_newWithSeed(alloc, logger, evilSeed, NULL);
 }
 
 struct Context
 {
     struct Allocator* alloc;
-    struct CryptoAuth* ca;
-    struct CryptoAuth_Session* sess;
+    TestCa_t* ca;
+    TestCa_Session_t* sess;
+    struct Iface plaintext;
+    struct Iface ciphertext;
     struct Log* log;
     struct EventBase* base;
 };
 
+static Iface_DEFUN doNothingSuccessfully(struct Message* msg, struct Iface* iface)
+{
+    return NULL;
+}
+
 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));
+    ctx->ciphertext.send = doNothingSuccessfully;
+    ctx->plaintext.send = doNothingSuccessfully;
+    TestCa_t* ca = ctx->ca =
+        TestCa_new(alloc, myPrivateKey, base, log,
+            evilRandom(alloc, 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);
+    Iface_plumb(&ctx->plaintext, &sess->plaintext);
+    Iface_plumb(&ctx->ciphertext, &sess->ciphertext);
 
     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 Message* msg = Message_new(0, CryptoHeader_SIZE + 12, alloc);
+    struct Context* ctx = setUp(NULL, HERPUBKEY, password, alloc, cfg);
+    struct Message* msg = Message_new(0, CryptoHeader_SIZE + 32, alloc);
     Er_assert(Message_epush(msg, HELLOWORLD, HELLOWORLDLEN));
 
-    Assert_true(!CryptoAuth_encrypt(ctx->sess, msg));
+    Iface_send(&ctx->plaintext, msg);
 
-    char* actual = Hex_print(msg->bytes, msg->length, alloc);
+    char* actual = Hex_print(msg->msgbytes, Message_getLength(msg), alloc);
     if (CString_strcmp(actual, expectedOutput)) {
         Assert_failure("Test failed.\n"
                        "Expected %s\n"
@@ -118,49 +106,53 @@ 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 Message* msg = Message_new(132, 0, alloc);
-    Assert_true(Hex_decode(msg->bytes, msg->length,
+    struct Context* ctx = setUp(PRIVATEKEY, herPublic, NULL, alloc, cfg);
+    struct Message* msg = Message_new(132, 32, alloc);
+    Assert_true(Hex_decode(msg->msgbytes, Message_getLength(msg),
         "0000000000ffffffffffffff7fffffffffffffffffffffffffffffffffffffff"
         "ffffffffffffffff847c0d2c375234f365e660955187a3735a0f7613d1609d3a"
         "6a4d8c53aeaa5a22ea9cf275eee0185edf7f211192f12e8e642a325ed76925fe"
         "3c76d313b767a10aca584ca0b979dee990a737da7d68366fa3846d43d541de91"
         "29ea3e12", 132*2) > 0);
+    Er_assert(Message_epush(msg, NULL, 16)); // peer ipv6
+
+    Iface_send(&ctx->ciphertext, msg);
+    uint32_t err = Er_assert(Message_epop32h(msg));
+    Assert_true(!err);
 
-    Assert_true(!CryptoAuth_decrypt(ctx->sess, msg));
-    Assert_true(msg->length == HELLOWORLDLEN);
-    Assert_true(Bits_memcmp(HELLOWORLD, msg->bytes, HELLOWORLDLEN) == 0);
+    Assert_true(Message_getLength(msg) == HELLOWORLDLEN);
+    Assert_true(Bits_memcmp(HELLOWORLD, msg->msgbytes, 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,18 +162,18 @@ static void repeatHello()
         "24e7e550";
 
     struct Allocator* alloc = MallocAllocator_new(1<<20);
-    struct Context* ctx = setUp(NULL, HERPUBKEY, "password", alloc);
-    struct Message* msg = Message_new(0, CryptoHeader_SIZE + HELLOWORLDLEN, alloc);
+    struct Context* ctx = setUp(NULL, HERPUBKEY, "password", alloc, cfg);
+    struct Message* msg = Message_new(0, CryptoHeader_SIZE + HELLOWORLDLEN + 32, alloc);
     Er_assert(Message_epush(msg, HELLOWORLD, HELLOWORLDLEN));
 
-    Assert_true(!CryptoAuth_encrypt(ctx->sess, msg));
+    Iface_send(&ctx->plaintext, msg);
 
     Message_reset(msg);
     Er_assert(Message_epush(msg, HELLOWORLD, HELLOWORLDLEN));
 
-    Assert_true(!CryptoAuth_encrypt(ctx->sess, msg));
+    Iface_send(&ctx->plaintext, msg);
 
-    char* actual = Hex_print(msg->bytes, msg->length, alloc);
+    char* actual = Hex_print(msg->msgbytes, Message_getLength(msg), alloc);
     if (CString_strcmp(actual, expectedOutput)) {
         Assert_failure("Test failed.\n"
                        "Expected %s\n"
@@ -190,38 +182,47 @@ 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), 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;
 }

+ 358 - 0
crypto/test/TestCa.c

@@ -0,0 +1,358 @@
+/* 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"
+#include "util/Hex.h"
+
+struct TestCa_s {
+    RTypes_CryptoAuth2_t* ca2;
+    struct CryptoAuth* ca;
+    bool noise;
+};
+typedef struct TestCa_Session_pvt_s {
+    TestCa_Session_t pub;
+    RTypes_CryptoAuth2_Session_t* s2;
+    struct CryptoAuth_Session* s;
+    struct Iface sPlain;
+    struct Iface sCipher;
+    struct Iface s2Plain;
+    struct Iface s2Cipher;
+    Identity
+} TestCa_Session_pvt_t;
+
+TestCa_t* TestCa_new(
+    Allocator_t *allocator,
+    const uint8_t *privateKey,
+    struct EventBase* eventBase,
+    struct Log* logger,
+    struct Random* rand0,
+    struct Random* rand1,
+    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, rand0);
+    }
+    if (cfg == TestCa_Config_OLD_NEW || cfg == TestCa_Config_NOISE) {
+        out->ca2 = Rffi_CryptoAuth2_new(allocator, privateKey, rand1);
+    }
+    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;
+}
+
+#define PASS 1
+#define STOP 2
+#define VERIFY 3
+
+#include <stdio.h>
+
+static Iface_DEFUN messagePlaintext(Message_t *msg, struct Iface* iface)
+{
+    TestCa_Session_pvt_t* sess = Identity_containerOf(iface, TestCa_Session_pvt_t, pub.plaintext);
+    Message_t* m2 = NULL;
+    if (sess->s2) {
+        if (sess->s) {
+            m2 = Message_clone(msg, Message_getAlloc(msg));
+        } else {
+            m2 = msg;
+            msg = NULL;
+        }
+    }
+    struct RTypes_Error_t* i1 = NULL;
+    if (sess->s) {
+        int flag = sess->s2 ? STOP : PASS;
+        Er_assert(Message_epushAd(msg, &flag, sizeof flag));
+        printf("Send [%d]\n", flag);
+        i1 = Iface_send(&sess->sPlain, msg);
+    }
+    if (sess->s2) {
+        if (sess->s) {
+            Er_assert(Message_epushAd(m2, &msg, sizeof &msg));
+        }
+        int flag = sess->s ? VERIFY : PASS;
+        Er_assert(Message_epushAd(m2, &flag, sizeof flag));
+        printf("Send2 [%d]\n", flag);
+        struct RTypes_Error_t* i2 = Iface_send(&sess->s2Plain, m2);
+        if (sess->s) {
+            Assert_true((i2 == NULL) == (i1 == NULL));
+        }
+        printf("Send2 done\n");
+        return i2;
+    }
+    return i1;
+}
+
+static Iface_DEFUN messageCiphertext(Message_t *msg, struct Iface* iface)
+{
+    TestCa_Session_pvt_t* sess = Identity_containerOf(iface, TestCa_Session_pvt_t, pub.ciphertext);
+    Message_t* m2 = NULL;
+    if (sess->s2) {
+        if (sess->s) {
+            m2 = Message_clone(msg, Message_getAlloc(msg));
+        } else {
+            m2 = msg;
+            msg = NULL;
+        }
+    }
+    struct RTypes_Error_t* i1 = NULL;
+    if (sess->s) {
+        int flag = sess->s2 ? STOP : PASS;
+        Er_assert(Message_epushAd(msg, &flag, sizeof flag));
+        i1 = Iface_send(&sess->sCipher, msg);
+    }
+    if (sess->s2) {
+        int flag = PASS;
+        if (sess->s) {
+            uintptr_t mp = (uintptr_t)msg;
+            Er_assert(Message_epushAd(m2, &mp, sizeof &mp));
+            flag = VERIFY;
+        }
+        Er_assert(Message_epushAd(m2, &flag, sizeof flag));
+        struct RTypes_Error_t* i2 = Iface_send(&sess->s2Cipher, m2);
+        if (sess->s) {
+            Assert_true((i2 == NULL) == (i1 == NULL));
+        }
+        return i2;
+    }
+    return i1;
+}
+
+static bool check(Message_t *msg, TestCa_Session_pvt_t* sess)
+{
+    int flag = 0;
+    Er_assert(Message_epopAd(msg, &flag, sizeof flag));
+    if (flag == PASS) {
+        printf("Passing message\n");
+    } else if (flag == STOP) {
+        // do nothing, wait for the next message to come through....
+        printf("Stopping message\n");
+        return true;
+    } else if (flag == VERIFY) {
+        uintptr_t m2p = 0;
+        Er_assert(Message_epopAd(msg, &m2p, sizeof m2p));
+        printf("Verifying message %lx\n", m2p);
+        struct Message* m2 = (struct Message*) m2p;
+        if (Message_getLength(msg) != Message_getLength(m2)) {
+            Assert_failure("Message_getLength(msg) != m2->length: %d != %d",
+                Message_getLength(msg), Message_getLength(m2));
+        }
+        if (Bits_memcmp(msg->msgbytes, m2->msgbytes, Message_getLength(msg))) {
+            const char* msgH = Hex_print(msg->msgbytes, Message_getLength(msg), Message_getAlloc(msg));
+            const char* m2H = Hex_print(m2->msgbytes, Message_getLength(m2), Message_getAlloc(m2));
+            Assert_failure("msg->bytes != m2->bytes:\n%s\n%s\n", msgH, m2H);
+        }
+        Assert_true(!Bits_memcmp(msg->msgbytes, m2->msgbytes, Message_getLength(msg)));
+    } else {
+        Assert_failure("unexpected flag [%d]", flag);
+    }
+    return false;
+}
+
+static Iface_DEFUN sPlainRecv(Message_t *msg, struct Iface* iface)
+{
+    TestCa_Session_pvt_t* sess = Identity_containerOf(iface, TestCa_Session_pvt_t, sPlain);
+    if (check(msg, sess)) { return NULL; }
+    return Iface_next(&sess->pub.plaintext, msg);
+}
+
+static Iface_DEFUN s2PlainRecv(Message_t *msg, struct Iface* iface)
+{
+    TestCa_Session_pvt_t* sess = Identity_containerOf(iface, TestCa_Session_pvt_t, s2Plain);
+    if (check(msg, sess)) { return NULL; }
+    return Iface_next(&sess->pub.plaintext, msg);
+}
+
+static Iface_DEFUN sCipherRecv(Message_t *msg, struct Iface* iface)
+{
+    TestCa_Session_pvt_t* sess = Identity_containerOf(iface, TestCa_Session_pvt_t, sCipher);
+    if (check(msg, sess)) { return NULL; }
+    return Iface_next(&sess->pub.ciphertext, msg);
+}
+
+static Iface_DEFUN s2CipherRecv(Message_t *msg, struct Iface* iface)
+{
+    TestCa_Session_pvt_t* sess = Identity_containerOf(iface, TestCa_Session_pvt_t, s2Cipher);
+    if (check(msg, sess)) { return NULL; }
+    return Iface_next(&sess->pub.ciphertext, msg);
+}
+
+TestCa_Session_t* TestCa_newSession(
+    TestCa_t *ca,
+    Allocator_t *alloc,
+    const uint8_t *herPublicKey,
+    bool requireAuth,
+    char *name,
+    bool useNoise)
+{
+    TestCa_Session_pvt_t* out = Allocator_calloc(alloc, sizeof(TestCa_Session_pvt_t), 1);
+    Identity_set(out);
+    out->sCipher.send = sCipherRecv;
+    out->sPlain.send = sPlainRecv;
+    out->s2Cipher.send = s2CipherRecv;
+    out->s2Plain.send = s2PlainRecv;
+    if (ca->ca) {
+        out->s = CryptoAuth_newSession(ca->ca, alloc, herPublicKey, requireAuth, name, false);
+        Iface_plumb(&out->sCipher, &out->s->ciphertext);
+        Iface_plumb(&out->sPlain, &out->s->plaintext);
+    }
+    if (ca->ca2) {
+        out->s2 = Rffi_CryptoAuth2_newSession(
+            ca->ca2, alloc, herPublicKey, requireAuth, name, ca->noise && useNoise);
+        Iface_plumb(&out->s2Cipher, out->s2->ciphertext);
+        Iface_plumb(&out->s2Plain, out->s2->plaintext);
+    }
+    out->pub.plaintext.send = messagePlaintext;
+    out->pub.ciphertext.send = messageCiphertext;
+    return &out->pub;
+}
+
+void TestCa_setAuth(const String_t* password, const String_t* login, TestCa_Session_t* session)
+{
+    TestCa_Session_pvt_t* sess = Identity_check((TestCa_Session_pvt_t*) session);
+    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* session)
+{
+    TestCa_Session_pvt_t* sess = Identity_check((TestCa_Session_pvt_t*) session);
+    if (sess->s) {
+        CryptoAuth_resetIfTimeout(sess->s);
+    }
+    if (sess->s2) {
+        Rffi_CryptoAuth2_resetIfTimeout(sess->s2);
+    }
+}
+
+void TestCa_reset(TestCa_Session_t* session)
+{
+    TestCa_Session_pvt_t* sess = Identity_check((TestCa_Session_pvt_t*) session);
+    if (sess->s) {
+        CryptoAuth_reset(sess->s);
+    }
+    if (sess->s2) {
+        Rffi_CryptoAuth2_reset(sess->s2);
+    }
+}
+
+RTypes_CryptoAuth_State_t TestCa_getState(TestCa_Session_t* session)
+{
+    TestCa_Session_pvt_t* sess = Identity_check((TestCa_Session_pvt_t*) session);
+    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* session, uint8_t* buf)
+{
+    TestCa_Session_pvt_t* sess = Identity_check((TestCa_Session_pvt_t*) session);
+    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);
+}

+ 79 - 0
crypto/test/TestCa.h

@@ -0,0 +1,79 @@
+/* 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 "interface/Iface.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 {
+    struct Iface plaintext;
+    struct Iface ciphertext;
+} 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* rand0,
+    struct Random* rand1,
+    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);
+
+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

+ 41 - 35
dht/Pathfinder.c

@@ -88,12 +88,17 @@ static int incomingFromDHT(struct DHTMessage* dmessage, void* vpf)
         DHTModuleRegistry_handleIncoming(dmessage, pf->registry);
         return 0;
     }
+    // This seems to be happening, this whole section of the code is deprecated so lets not
+    // try to debug it too much and just squash the message.
+    if (addr->path == 0xffffffffffffffffull) {
+        return 0;
+    }
 
     // Sanity check (make sure the addr was actually calculated)
     Assert_true(AddressCalc_validAddress(addr->ip6.bytes));
 
     Er_assert(Message_eshift(msg, PFChan_Msg_MIN_SIZE));
-    struct PFChan_Msg* emsg = (struct PFChan_Msg*) msg->bytes;
+    struct PFChan_Msg* emsg = (struct PFChan_Msg*) msg->msgbytes;
     Bits_memset(emsg, 0, PFChan_Msg_MIN_SIZE);
 
     DataHeader_setVersion(&emsg->data, DataHeader_CURRENT_VERSION);
@@ -108,6 +113,7 @@ static int incomingFromDHT(struct DHTMessage* dmessage, void* vpf)
 
     Assert_true(!Bits_isZero(emsg->route.publicKey, 32));
     Assert_true(emsg->route.sh.label_be);
+    Assert_true(emsg->route.sh.label_be != 0xffffffffffffffffull);
     Assert_true(emsg->route.version_be);
 
     Er_assert(Message_epush32be(msg, PFChan_Pathfinder_SENDMSG));
@@ -141,9 +147,9 @@ static Iface_DEFUN sendNode(struct Message* msg,
 {
     Message_reset(msg);
     Er_assert(Message_eshift(msg, PFChan_Node_SIZE));
-    nodeForAddress((struct PFChan_Node*) msg->bytes, addr, metric);
+    nodeForAddress((struct PFChan_Node*) msg->msgbytes, addr, metric);
     if (addr->path == UINT64_MAX) {
-        ((struct PFChan_Node*) msg->bytes)->path_be = 0;
+        ((struct PFChan_Node*) msg->msgbytes)->path_be = 0;
     }
     Er_assert(Message_epush32be(msg, PFChan_Pathfinder_NODE));
     return Iface_next(&pf->pub.eventIf, msg);
@@ -172,7 +178,7 @@ static Iface_DEFUN connected(struct Pathfinder_pvt* pf, struct Message* msg)
 
     struct PFChan_Core_Connect conn;
     Er_assert(Message_epop(msg, &conn, PFChan_Core_Connect_SIZE));
-    Assert_true(!msg->length);
+    Assert_true(!Message_getLength(msg));
 
     Bits_memcpy(pf->myAddr.key, conn.publicKey, 32);
     Address_getPrefix(&pf->myAddr);
@@ -237,14 +243,14 @@ static Iface_DEFUN connected(struct Pathfinder_pvt* pf, struct Message* msg)
 
     pf->state = Pathfinder_pvt_state_RUNNING;
 
-    return Error(NONE);
+    return NULL;
 }
 
 static void addressForNode(struct Address* addrOut, struct Message* msg)
 {
     struct PFChan_Node node;
     Er_assert(Message_epop(msg, &node, PFChan_Node_SIZE));
-    Assert_true(!msg->length);
+    Assert_true(!Message_getLength(msg));
     addrOut->protocolVersion = Endian_bigEndianToHost32(node.version_be);
     addrOut->path = Endian_bigEndianToHost64(node.path_be);
     Bits_memcpy(addrOut->key, node.publicKey, 32);
@@ -262,7 +268,7 @@ static Iface_DEFUN switchErr(struct Message* msg, struct Pathfinder_pvt* pf)
     uint8_t pathStr[20];
     AddrTools_printPath(pathStr, path);
     int err = Endian_bigEndianToHost32(switchErr.ctrlErr.errorType_be);
-    Log_debug(pf->log, "switch err from [%s] type [%s][%d]", pathStr, Error_strerror(err), err);
+    Log_debug(pf->log, "switch err from [%s] type [%d]", pathStr, err);
 
     struct Node_Link* link = NodeStore_linkForPath(pf->nodeStore, path);
     uint8_t nodeAddr[16];
@@ -277,7 +283,7 @@ static Iface_DEFUN switchErr(struct Message* msg, struct Pathfinder_pvt* pf)
         SearchRunner_search(nodeAddr, 20, 3, pf->searchRunner, pf->alloc);
     }
 
-    return Error(NONE);
+    return NULL;
 }
 
 static Iface_DEFUN searchReq(struct Message* msg, struct Pathfinder_pvt* pf)
@@ -286,8 +292,8 @@ static Iface_DEFUN searchReq(struct Message* msg, struct Pathfinder_pvt* pf)
     Er_assert(Message_epop(msg, addr, 16));
     Er_assert(Message_epop32be(msg));
     uint32_t version = Er_assert(Message_epop32be(msg));
-    if (version && version >= 20) { return Error(NONE); }
-    Assert_true(!msg->length);
+    if (version && version >= 20) { return NULL; }
+    Assert_true(!Message_getLength(msg));
     uint8_t printedAddr[40];
     AddrTools_printIp(printedAddr, addr);
     Log_debug(pf->log, "Search req [%s]", printedAddr);
@@ -298,14 +304,14 @@ static Iface_DEFUN searchReq(struct Message* msg, struct Pathfinder_pvt* pf)
     } else {
         SearchRunner_search(addr, 20, 3, pf->searchRunner, pf->alloc);
     }
-    return Error(NONE);
+    return NULL;
 }
 
 static Iface_DEFUN peer(struct Message* msg, struct Pathfinder_pvt* pf)
 {
-    struct Address addr;
+    struct Address addr = {0};
     addressForNode(&addr, msg);
-    String* str = Address_toString(&addr, msg->alloc);
+    String* str = Address_toString(&addr, Message_getAlloc(msg));
     Log_debug(pf->log, "Peer [%s]", str->bytes);
 
     struct Node_Link* link = NodeStore_linkForPath(pf->nodeStore, addr.path);
@@ -315,7 +321,7 @@ static Iface_DEFUN peer(struct Message* msg, struct Pathfinder_pvt* pf)
         && Node_getBestParent(link->child)->parent->address.path == 1
         && Node_getBestParent(link->child)->cannonicalLabel == addr.path)
     {
-        return Error(NONE);
+        return NULL;
     }
     //RumorMill_addNode(pf->rumorMill, &addr);
     Router_sendGetPeers(pf->router, &addr, 0, 0, pf->alloc);
@@ -325,9 +331,9 @@ static Iface_DEFUN peer(struct Message* msg, struct Pathfinder_pvt* pf)
 
 static Iface_DEFUN peerGone(struct Message* msg, struct Pathfinder_pvt* pf)
 {
-    struct Address addr;
+    struct Address addr = {0};
     addressForNode(&addr, msg);
-    String* str = Address_toString(&addr, msg->alloc);
+    String* str = Address_toString(&addr, Message_getAlloc(msg));
     Log_debug(pf->log, "Peer gone [%s]", str->bytes);
     NodeStore_disconnectedPeer(pf->nodeStore, addr.path);
 
@@ -337,9 +343,9 @@ static Iface_DEFUN peerGone(struct Message* msg, struct Pathfinder_pvt* pf)
 
 static Iface_DEFUN session(struct Message* msg, struct Pathfinder_pvt* pf)
 {
-    struct Address addr;
+    struct Address addr = {0};
     addressForNode(&addr, msg);
-    String* str = Address_toString(&addr, msg->alloc);
+    String* str = Address_toString(&addr, Message_getAlloc(msg));
     Log_debug(pf->log, "Session [%s]", str->bytes);
 
     /* This triggers for every little ping we send to some random node out there which
@@ -349,40 +355,40 @@ static Iface_DEFUN session(struct Message* msg, struct Pathfinder_pvt* pf)
         SearchRunner_search(addr.ip6.bytes, 20, 3, pf->searchRunner, pf->alloc);
     }*/
 
-    return Error(NONE);
+    return NULL;
 }
 
 static Iface_DEFUN sessionEnded(struct Message* msg, struct Pathfinder_pvt* pf)
 {
-    struct Address addr;
+    struct Address addr = {0};
     addressForNode(&addr, msg);
-    String* str = Address_toString(&addr, msg->alloc);
+    String* str = Address_toString(&addr, Message_getAlloc(msg));
     Log_debug(pf->log, "Session ended [%s]", str->bytes);
-    return Error(NONE);
+    return NULL;
 }
 
 static Iface_DEFUN discoveredPath(struct Message* msg, struct Pathfinder_pvt* pf)
 {
-    struct Address addr;
+    struct Address addr = {0};
     addressForNode(&addr, msg);
 
     // We're somehow aware of this path (even if it's unused)
-    if (NodeStore_linkForPath(pf->nodeStore, addr.path)) { return Error(NONE); }
+    if (NodeStore_linkForPath(pf->nodeStore, addr.path)) { return NULL; }
 
     // If we don't already care about the destination, then don't do anything.
     struct Node_Two* nn = NodeStore_nodeForAddr(pf->nodeStore, addr.ip6.bytes);
-    if (!nn) { return Error(NONE); }
+    if (!nn) { return NULL; }
 
     // Our best path is "shorter" (label bits which is somewhat representitive of hop count)
     // basically this is just to dampen the flood to the RM because otherwise it prevents Janitor
     // from getting any actual work done.
-    if (nn->address.path < addr.path) { return Error(NONE); }
+    if (nn->address.path < addr.path) { return NULL; }
 
     addr.protocolVersion = nn->address.protocolVersion;
 
-    Log_debug(pf->log, "Discovered path [%s]", Address_toString(&addr, msg->alloc)->bytes);
+    Log_debug(pf->log, "Discovered path [%s]", Address_toString(&addr, Message_getAlloc(msg))->bytes);
     RumorMill_addNode(pf->rumorMill, &addr);
-    return Error(NONE);
+    return NULL;
 }
 
 static Iface_DEFUN handlePing(struct Message* msg, struct Pathfinder_pvt* pf)
@@ -395,13 +401,13 @@ static Iface_DEFUN handlePing(struct Message* msg, struct Pathfinder_pvt* pf)
 static Iface_DEFUN handlePong(struct Message* msg, struct Pathfinder_pvt* pf)
 {
     Log_debug(pf->log, "Received pong");
-    return Error(NONE);
+    return NULL;
 }
 
 static Iface_DEFUN incomingMsg(struct Message* msg, struct Pathfinder_pvt* pf)
 {
-    struct Address addr;
-    struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes;
+    struct Address addr = {0};
+    struct RouteHeader* hdr = (struct RouteHeader*) msg->msgbytes;
     Er_assert(Message_eshift(msg, -(RouteHeader_SIZE + DataHeader_SIZE)));
     Bits_memcpy(addr.ip6.bytes, hdr->ip6, 16);
     Bits_memcpy(addr.key, hdr->publicKey, 32);
@@ -414,12 +420,12 @@ static Iface_DEFUN incomingMsg(struct Message* msg, struct Pathfinder_pvt* pf)
     struct DHTMessage dht = {
         .address = &addr,
         .binMessage = msg,
-        .allocator = msg->alloc
+        .allocator = Message_getAlloc(msg)
     };
 
     DHTModuleRegistry_handleIncoming(&dht, pf->registry);
 
-    struct Message* nodeMsg = Message_new(0, 256, msg->alloc);
+    struct Message* nodeMsg = Message_new(0, 256, Message_getAlloc(msg));
     Iface_CALL(sendNode, nodeMsg, &addr, Metric_DHT_INCOMING, pf);
 
     if (dht.pleaseRespond) {
@@ -427,7 +433,7 @@ static Iface_DEFUN incomingMsg(struct Message* msg, struct Pathfinder_pvt* pf)
         return Iface_next(&pf->pub.eventIf, msg);
     }
 
-    return Error(NONE);
+    return NULL;
 }
 
 static Iface_DEFUN incomingFromEventIf(struct Message* msg, struct Iface* eventIf)
@@ -453,7 +459,7 @@ static Iface_DEFUN incomingFromEventIf(struct Message* msg, struct Iface* eventI
         case PFChan_Core_PONG: return handlePong(msg, pf);
         case PFChan_Core_UNSETUP_SESSION:
         case PFChan_Core_LINK_STATE:
-        case PFChan_Core_CTRL_MSG: return Error(NONE);
+        case PFChan_Core_CTRL_MSG: return NULL;
         default:;
     }
     Assert_failure("unexpected event [%d]", ev);

+ 1 - 1
dht/ReplyModule.c

@@ -68,7 +68,7 @@ static int handleIncoming(struct DHTMessage* message, void* vcontext)
         Address_toString(message->address, message->allocator)->bytes);
 
     Message_reset(message->binMessage);
-    Assert_true(!((uintptr_t)message->binMessage->bytes % 4) || !"alignment fault0");
+    Assert_true(!((uintptr_t)message->binMessage->msgbytes % 4) || !"alignment fault0");
 
     struct DHTMessage* reply = Allocator_clone(message->allocator, (&(struct DHTMessage) {
         .replyTo = message,

+ 5 - 5
dht/SerializationModule.c

@@ -71,8 +71,8 @@ static int handleOutgoing(struct DHTMessage* message,
                           void* vcontext)
 {
    // This is always at the end of the message.
-    Assert_true(!message->binMessage->length);
-    Assert_true(!((uintptr_t)message->binMessage->bytes % 4) || !"alignment fault0");
+    Assert_true(!Message_getLength(message->binMessage));
+    Assert_true(!((uintptr_t)message->binMessage->msgbytes % 4) || !"alignment fault0");
 
     if (Dict_getStringC(message->asDict, "q")) {
         String* txid = Dict_getStringC(message->asDict, "txid");
@@ -86,7 +86,7 @@ static int handleOutgoing(struct DHTMessage* message,
 
     Er_assert(BencMessageWriter_write(message->asDict, message->binMessage));
 
-    Assert_true(!((uintptr_t)message->binMessage->bytes % 4) || !"alignment fault");
+    Assert_true(!((uintptr_t)message->binMessage->msgbytes % 4) || !"alignment fault");
 
     return 0;
 }
@@ -106,9 +106,9 @@ static int handleIncoming(struct DHTMessage* message,
         Log_info(context->logger, "Failed to parse message [%s]", err);
         return -2;
     }
-    if (message->binMessage->length) {
+    if (Message_getLength(message->binMessage)) {
         Log_info(context->logger, "Message contains [%d] bytes of crap at the end",
-                 (int)message->binMessage->length);
+                 (int)Message_getLength(message->binMessage));
     }
 
     String* q = Dict_getStringC(message->asDict, "q");

+ 5 - 5
dht/dhtcore/Janitor.c

@@ -101,7 +101,7 @@ struct Janitor_Search
 
 static bool isBlacklisted(struct Janitor_pvt* j, uint64_t path)
 {
-    int64_t now = Time_currentTimeMilliseconds(j->eventBase);
+    int64_t now = Time_currentTimeMilliseconds();
     for (int i = 0; i < Janitor_pvt_blacklist_NUM; i++) {
         struct Janitor_Blacklist* qp = &j->blacklist[i];
         if (qp->path == path && now - qp->timeAdded < j->pub.blacklistPathForMilliseconds) {
@@ -113,7 +113,7 @@ static bool isBlacklisted(struct Janitor_pvt* j, uint64_t path)
 
 static void blacklist(struct Janitor_pvt* j, uint64_t path)
 {
-    int64_t now = Time_currentTimeMilliseconds(j->eventBase);
+    int64_t now = Time_currentTimeMilliseconds();
     int oldestIndex = 0;
     int64_t oldestTime = INT64_MAX;
     for (int i = 0; i < Janitor_pvt_blacklist_NUM; i++) {
@@ -371,7 +371,7 @@ static void peersResponseCallback(struct RouterModule_Promise* promise,
  */
 static void keyspaceMaintenance(struct Janitor_pvt* janitor)
 {
-    struct Address addr;
+    struct Address addr = {0};
     struct Address* selfAddr = janitor->nodeStore->selfAddress;
     if (!RumorMill_getNode(janitor->pub.dhtMill, &addr)) {
         // Try to fill the dhtMill for next time.
@@ -598,7 +598,7 @@ static void maintanenceCycle(void* vcontext)
 {
     struct Janitor_pvt* const janitor = Identity_check((struct Janitor_pvt*) vcontext);
 
-    uint64_t now = Time_currentTimeMilliseconds(janitor->eventBase);
+    uint64_t now = Time_currentTimeMilliseconds();
 
     uint64_t nextTimeout = (janitor->pub.localMaintainenceMilliseconds / 2);
     nextTimeout += Random_uint32(janitor->rand) % (nextTimeout * 2);
@@ -705,7 +705,7 @@ struct Janitor* Janitor_new(struct RouterModule* routerModule,
     janitor->pub.localMaintainenceMilliseconds = Janitor_LOCAL_MAINTENANCE_MILLISECONDS_DEFAULT;
     janitor->pub.blacklistPathForMilliseconds = Janitor_BLACKLIST_PATH_FOR_MILLISECONDS_DEFAULT;
 
-    janitor->timeOfNextGlobalMaintainence = Time_currentTimeMilliseconds(eventBase);
+    janitor->timeOfNextGlobalMaintainence = Time_currentTimeMilliseconds();
 
     janitor->timeout = Timeout_setTimeout(maintanenceCycle,
                                           janitor,

+ 6 - 6
dht/dhtcore/NodeStore.c

@@ -622,7 +622,7 @@ static struct Node_Link* linkNodes(struct Node_Two* parent,
     link->parent = parent;
     link->discoveredPath = discoveredPath;
     link->linkCost = 0;
-    link->timeLastSeen = Time_currentTimeMilliseconds(store->eventBase);
+    link->timeLastSeen = Time_currentTimeMilliseconds();
     Identity_set(link);
 
     // reverse link
@@ -1358,7 +1358,7 @@ static struct Node_Link* discoverNode(struct NodeStore_pvt* store,
         child->alloc = alloc;
         Bits_memcpy(&child->address, addr, sizeof(struct Address));
         child->encodingScheme = EncodingScheme_clone(scheme, child->alloc);
-        child->timeLastPinged = Time_currentTimeMilliseconds(store->eventBase);
+        child->timeLastPinged = Time_currentTimeMilliseconds();
         Identity_set(child);
     }
 
@@ -1393,7 +1393,7 @@ static struct Node_Link* discoverNode(struct NodeStore_pvt* store,
         } while (firstHopInPath_INVALID != path);
 
         if (lastLink && LabelSplicer_routesThrough(addr->path, lastLink->child->address.path)) {
-            // checking for sillyness...
+            // checking for silliness...
             Assert_true(lastLink != store->selfLink);
             NodeStore_unlinkNodes(&store->pub, lastLink);
             continue;
@@ -1639,7 +1639,7 @@ struct NodeStore* NodeStore_new(struct Address* myAddress,
     Identity_set(selfNode);
     out->pub.selfNode = selfNode;
     linkNodes(selfNode, selfNode, 1, 0, 0, 1, out);
-    selfNode->timeLastPinged = Time_currentTimeMilliseconds(out->eventBase);
+    selfNode->timeLastPinged = Time_currentTimeMilliseconds();
 
     out->pub.selfAddress = &out->selfLink->child->address;
     out->pub.selfAddress->protocolVersion = Version_CURRENT_PROTOCOL;
@@ -2011,7 +2011,7 @@ static void updatePathCost(struct NodeStore_pvt* store, const uint64_t path, uin
 {
     struct Node_Link* link = store->selfLink;
     uint64_t pathFrag = path;
-    uint64_t now = Time_currentTimeMilliseconds(store->eventBase);
+    uint64_t now = Time_currentTimeMilliseconds();
     for (;;) {
         struct Node_Link* nextLink = NULL;
         uint64_t nextPath = firstHopInPath(pathFrag, &nextLink, link, store);
@@ -2135,7 +2135,7 @@ uint16_t NodeStore_bucketForAddr(struct Address* source, struct Address* dest)
 uint64_t NodeStore_timeSinceLastPing(struct NodeStore* nodeStore, struct Node_Two* node)
 {
     struct NodeStore_pvt* store = Identity_check((struct NodeStore_pvt*)nodeStore);
-    uint64_t now = Time_currentTimeMilliseconds(store->eventBase);
+    uint64_t now = Time_currentTimeMilliseconds();
     uint64_t lastSeen = node->timeLastPinged;
     struct Node_Link* link = Node_getBestParent(node);
     while (link && link != store->selfLink) {

+ 1 - 1
dht/dhtcore/RouterModule.c

@@ -466,7 +466,7 @@ static int handleIncoming(struct DHTMessage* message, void* vcontext)
 
     struct RouterModule* module = Identity_check((struct RouterModule*) vcontext);
 
-    // This is retreived below by onResponseOrTimeout()
+    // This is retrieved below by onResponseOrTimeout()
     module->currentMessage = message;
     Pinger_pongReceived(txid, module->pinger);
     module->currentMessage = NULL;

+ 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"

+ 4 - 4
doc/Whitepaper.md

@@ -524,7 +524,7 @@ The Switch Header may be followed by three different types of packets:
   The CryptoAuth handshake packet contains the Session Handle (that should
   be used by the recipient to prefix CryptoAuth data packets sent after that),
   eventually followed by a Switch Data Header.
-* Otherwise, these first four bytes are a Session Handle, which the receipient
+* Otherwise, these first four bytes are a Session Handle, which the recipient
   of these packet chose earlier to identify the emitted. They are followed
   by a CryptoAuth Data Packet, containing a Switch Data Header.
 
@@ -658,7 +658,7 @@ Possible keys in a router message include:
 * `p` (integer): protocol version. Matches the cjdns version.
 * `tar` (byte string): the target address. If provided, contains an address
   the sender wants to reach.
-* `txid` (byte string): transaction id. Opaque value choosen by senders of
+* `txid` (byte string): transaction id. Opaque value chosen by senders of
   queries, which must be used in responses.
 
 The serialization of each item of the list of nodes `n` is:
@@ -902,7 +902,7 @@ assuming they are not “too late” and are not replays.
 To do that, it stores a 64-bit bitfield, with a bit for each of the 64
 nonces before the highest nonce received so far.
 Every time a packet is received with a nonce between `highestnonce - 64`
-(excluded) and `highestnonce` (included), it substracts the packet's nonce
+(excluded) and `highestnonce` (included), it subtracts the packet's nonce
 to the highest nonce, giving a number n, and looks at the n-th bit
 of the bitfield. If it is one, the packet is a replay and is dropped.
 If it is zero, the packet passes, and the bit is set to one.
@@ -969,7 +969,7 @@ of the hash of the password (counting indexes from 1). This is used as a sort
 of username so that the other end knows which password to try using in the
 handshake.
 
-AuthType Two is prefered to this method because it may be harder to crack
+AuthType Two is preferred to this method because it may be harder to crack
 (does not leak bytes of the value computing from the password).
 
 ##### AuthType Two

+ 1 - 3
exception/Er.c

@@ -59,7 +59,5 @@ struct Er_Ret* Er__raise(char* file, int line, struct Allocator* alloc, char* fo
 void Er__assertFail(struct Er_Ret* er)
 {
     if (!er) { return; }
-    fprintf(stderr, "%s\n", er->message);
-    abort();
-    exit(100);
+    Assert_failure("%s", er->message);
 }

+ 4 - 4
interface/ASynchronizer.c

@@ -98,10 +98,10 @@ static Iface_DEFUN fromA(struct Message* msg, struct Iface* ifA)
     struct ASynchronizer_pvt* as = Identity_containerOf(ifA, struct ASynchronizer_pvt, pub.ifA);
     if (!as->cycleAlloc) { as->cycleAlloc = Allocator_child(as->alloc); }
     if (!as->msgsToB) { as->msgsToB = ArrayList_Messages_new(as->cycleAlloc); }
-    Allocator_adopt(as->cycleAlloc, msg->alloc);
+    Allocator_adopt(as->cycleAlloc, Message_getAlloc(msg));
     ArrayList_Messages_add(as->msgsToB, msg);
     checkTimeout(as);
-    return Error(NONE);
+    return NULL;
 }
 
 static Iface_DEFUN fromB(struct Message* msg, struct Iface* ifB)
@@ -109,10 +109,10 @@ static Iface_DEFUN fromB(struct Message* msg, struct Iface* ifB)
     struct ASynchronizer_pvt* as = Identity_containerOf(ifB, struct ASynchronizer_pvt, pub.ifB);
     if (!as->cycleAlloc) { as->cycleAlloc = Allocator_child(as->alloc); }
     if (!as->msgsToA) { as->msgsToA = ArrayList_Messages_new(as->cycleAlloc); }
-    Allocator_adopt(as->cycleAlloc, msg->alloc);
+    Allocator_adopt(as->cycleAlloc, Message_getAlloc(msg));
     ArrayList_Messages_add(as->msgsToA, msg);
     checkTimeout(as);
-    return Error(NONE);
+    return NULL;
 }
 
 struct ASynchronizer* ASynchronizer_new(struct Allocator* alloc,

+ 6 - 2
interface/ETHInterface_admin.c

@@ -46,6 +46,9 @@ static void beginConnection(Dict* args,
     int64_t* interfaceNumber = Dict_getIntC(args, "interfaceNumber");
     uint32_t ifNum = (interfaceNumber) ? ((uint32_t) *interfaceNumber) : 0;
     String* peerName = Dict_getStringC(args, "peerName");
+    int64_t* versionP = Dict_getIntC(args, "version");
+    int version = Version_DEFAULT_ASSUMPTION;
+    if (versionP) { version = *versionP; }
     char* error = "none";
 
     uint8_t pkBytes[32];
@@ -62,7 +65,7 @@ static void beginConnection(Dict* args,
         error = "invalid macAddress";
     } else {
         int ret = InterfaceController_bootstrapPeer(
-            ctx->ic, ifNum, pkBytes, &sockaddr.generic, password, login, peerName, ctx->alloc);
+            ctx->ic, ifNum, pkBytes, &sockaddr.generic, password, login, peerName, version);
 
         if (ret == InterfaceController_bootstrapPeer_BAD_IFNUM) {
             error = "invalid interfaceNumber";
@@ -194,7 +197,8 @@ void ETHInterface_admin_register(struct EventBase* base,
             { .name = "publicKey", .required = 1, .type = "String" },
             { .name = "macAddress", .required = 1, .type = "String" },
             { .name = "login", .required = 0, .type = "String" },
-            { .name = "peerName", .required = 0, .type = "String" }
+            { .name = "peerName", .required = 0, .type = "String" },
+            { .name = "version", .required = 0, .type = "Int" },
         }), admin);
 
     Admin_registerFunction("ETHInterface_beacon", beacon, ctx, true,

+ 14 - 14
interface/ETHInterface_darwin.c

@@ -73,8 +73,8 @@ static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* iface)
     struct ETHInterface_pvt* ctx =
         Identity_containerOf(iface, struct ETHInterface_pvt, pub.generic.iface);
 
-    struct Sockaddr* sa = (struct Sockaddr*) msg->bytes;
-    Assert_true(msg->length >= Sockaddr_OVERHEAD);
+    struct Sockaddr* sa = (struct Sockaddr*) msg->msgbytes;
+    Assert_true(Message_getLength(msg) >= Sockaddr_OVERHEAD);
     Assert_true(sa->addrLen <= ETHInterface_Sockaddr_SIZE);
 
     struct ETHInterface_Sockaddr sockaddr = { .generic = { .addrLen = 0 } };
@@ -83,7 +83,7 @@ static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* iface)
     struct ETHInterface_Header hdr = {
         .version = ETHInterface_CURRENT_VERSION,
         .zero = 0,
-        .length_be = Endian_hostToBigEndian16(msg->length + ETHInterface_Header_SIZE),
+        .length_be = Endian_hostToBigEndian16(Message_getLength(msg) + ETHInterface_Header_SIZE),
         .fc00_be = Endian_hostToBigEndian16(0xfc00)
     };
     Er_assert(Message_epush(msg, &hdr, ETHInterface_Header_SIZE));
@@ -100,16 +100,16 @@ static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* iface)
     Er_assert(Message_epush(msg, &ethFr, ethernet_frame_SIZE));
   /*
     struct bpf_hdr bpfPkt = {
-        .bh_caplen = msg->length,
-        .bh_datalen = msg->length,
+        .bh_caplen = Message_getLength(msg),
+        .bh_datalen = Message_getLength(msg),
         .bh_hdrlen = BPF_WORDALIGN(sizeof(struct bpf_hdr))
     };
     Er_assert(Message_epush(msg, &bpfPkt, bpfPkt.bh_hdrlen));
 */
-    if (msg->length != write(ctx->socket, msg->bytes, msg->length)) {
+    if (Message_getLength(msg) != write(ctx->socket, msg->msgbytes, Message_getLength(msg))) {
         Log_debug(ctx->logger, "Error writing to eth device [%s]", strerror(errno));
     }
-    return Error(NONE);
+    return NULL;
 }
 
 static void handleEvent2(struct ETHInterface_pvt* context,
@@ -130,7 +130,7 @@ static void handleEvent2(struct ETHInterface_pvt* context,
     struct ETHInterface_Header hdr;
     Bits_memcpy(&hdr, data, ETHInterface_Header_SIZE);
 
-    Bits_memcpy(msg->bytes, &data[ETHInterface_Header_SIZE], contentLength);
+    Bits_memcpy(msg->msgbytes, &data[ETHInterface_Header_SIZE], contentLength);
 
     // here we could put a switch statement to handle different versions differently.
     if (hdr.version != ETHInterface_CURRENT_VERSION) {
@@ -140,12 +140,12 @@ static void handleEvent2(struct ETHInterface_pvt* context,
 
     uint16_t reportedLength = Endian_bigEndianToHost16(hdr.length_be);
     reportedLength -= ETHInterface_Header_SIZE;
-    if (msg->length != reportedLength) {
-        if (msg->length < reportedLength) {
+    if (Message_getLength(msg) != reportedLength) {
+        if (Message_getLength(msg) < reportedLength) {
             Log_debug(context->logger, "DROP size field is larger than frame");
             return;
         }
-        msg->length = reportedLength;
+        Er_assert(Message_truncate(msg, reportedLength));
     }
     if (hdr.fc00_be != Endian_hostToBigEndian16(0xfc00)) {
         Log_debug(context->logger, "DROP bad magic");
@@ -161,7 +161,7 @@ static void handleEvent2(struct ETHInterface_pvt* context,
 
     Er_assert(Message_epush(msg, &sockaddr, ETHInterface_Sockaddr_SIZE));
 
-    Assert_true(!((uintptr_t)msg->bytes % 4) && "Alignment fault");
+    Assert_true(!((uintptr_t)msg->msgbytes % 4) && "Alignment fault");
 
     Iface_send(&context->pub.generic.iface, msg);
 }
@@ -230,8 +230,8 @@ static Er_DEFUN(int openBPF(struct Allocator* alloc))
 {
     for (int retry = 0; retry < 100; retry++) {
         for (int i = 0; i < 256; i++) {
-            char buf[11] = { 0 };
-            snprintf(buf, 10, "/dev/bpf%i", i);
+            char buf[21] = { 0 };
+            snprintf(buf, 20, "/dev/bpf%i", i);
             int bpf = open(buf, O_RDWR);
             if (bpf != -1) { Er_ret(bpf); }
         }

+ 15 - 16
interface/ETHInterface_linux.c

@@ -39,7 +39,7 @@
 #include <unistd.h>
 #include <errno.h>
 
-#ifndef android
+#ifndef Cjdns_android
     #include <ifaddrs.h>
 #endif
 
@@ -80,8 +80,8 @@ static void sendMessageInternal(struct Message* message,
     */
 
     if (sendto(context->socket,
-               message->bytes,
-               message->length,
+               message->msgbytes,
+               Message_getLength(message),
                0,
                (struct sockaddr*) addr,
                sizeof(struct sockaddr_ll)) < 0)
@@ -105,8 +105,8 @@ static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* iface)
     struct ETHInterface_pvt* ctx =
         Identity_containerOf(iface, struct ETHInterface_pvt, pub.generic.iface);
 
-    struct Sockaddr* sa = (struct Sockaddr*) msg->bytes;
-    Assert_true(msg->length >= Sockaddr_OVERHEAD);
+    struct Sockaddr* sa = (struct Sockaddr*) msg->msgbytes;
+    Assert_true(Message_getLength(msg) >= Sockaddr_OVERHEAD);
     Assert_true(sa->addrLen <= ETHInterface_Sockaddr_SIZE);
 
     struct ETHInterface_Sockaddr sockaddr = { .generic = { .addrLen = 0 } };
@@ -124,12 +124,12 @@ static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* iface)
     struct ETHInterface_Header hdr = {
         .version = ETHInterface_CURRENT_VERSION,
         .zero = 0,
-        .length_be = Endian_hostToBigEndian16(msg->length + ETHInterface_Header_SIZE),
+        .length_be = Endian_hostToBigEndian16(Message_getLength(msg) + ETHInterface_Header_SIZE),
         .fc00_be = Endian_hostToBigEndian16(0xfc00)
     };
     Er_assert(Message_epush(msg, &hdr, ETHInterface_Header_SIZE));
     sendMessageInternal(msg, &addr, ctx);
-    return Error(NONE);
+    return NULL;
 }
 
 static void handleEvent2(struct ETHInterface_pvt* context, struct Allocator* messageAlloc)
@@ -144,8 +144,8 @@ static void handleEvent2(struct ETHInterface_pvt* context, struct Allocator* mes
     Er_assert(Message_eshift(msg, 2));
 
     int rc = recvfrom(context->socket,
-                      msg->bytes,
-                      msg->length,
+                      msg->msgbytes,
+                      Message_getLength(msg),
                       0,
                       (struct sockaddr*) &addr,
                       &addrLen);
@@ -155,8 +155,7 @@ static void handleEvent2(struct ETHInterface_pvt* context, struct Allocator* mes
         return;
     }
 
-    Assert_true(msg->length >= rc);
-    msg->length = rc;
+    Er_assert(Message_truncate(msg, rc));
 
     //Assert_true(addrLen == SOCKADDR_LL_LEN);
 
@@ -171,12 +170,12 @@ static void handleEvent2(struct ETHInterface_pvt* context, struct Allocator* mes
 
     uint16_t reportedLength = Endian_bigEndianToHost16(hdr.length_be);
     reportedLength -= ETHInterface_Header_SIZE;
-    if (msg->length != reportedLength) {
-        if (msg->length < reportedLength) {
+    if (Message_getLength(msg) != reportedLength) {
+        if (Message_getLength(msg) < reportedLength) {
             Log_debug(context->logger, "DROP size field is larger than frame");
             return;
         }
-        msg->length = reportedLength;
+        Er_assert(Message_truncate(msg, reportedLength));
     }
     if (hdr.fc00_be != Endian_hostToBigEndian16(0xfc00)) {
         Log_debug(context->logger, "DROP bad magic");
@@ -192,7 +191,7 @@ static void handleEvent2(struct ETHInterface_pvt* context, struct Allocator* mes
 
     Er_assert(Message_epush(msg, &sockaddr, ETHInterface_Sockaddr_SIZE));
 
-    Assert_true(!((uintptr_t)msg->bytes % 4) && "Alignment fault");
+    Assert_true(!((uintptr_t)msg->msgbytes % 4) && "Alignment fault");
 
     Iface_send(&context->pub.generic.iface, msg);
 }
@@ -208,7 +207,7 @@ static void handleEvent(void* vcontext)
 Er_DEFUN(List* ETHInterface_listDevices(struct Allocator* alloc))
 {
     List* out = List_new(alloc);
-#ifndef android
+#ifndef Cjdns_android
     struct ifaddrs* ifaddr = NULL;
     if (getifaddrs(&ifaddr) || ifaddr == NULL) {
         Er_raise(alloc, "getifaddrs() -> errno:%d [%s]", errno, strerror(errno));

+ 32 - 34
interface/FramingIface.c

@@ -49,26 +49,28 @@ struct FramingIface_pvt {
 
 static struct Message* mergeMessage(struct FramingIface_pvt* fi, struct Message* last)
 {
-    int length = last->length;
+    int length = Message_getLength(last);
 
     // The only accurate way to get the full length because this last might contain
     // the beginning of the next frame.
     struct MessageList* part = fi->frameParts;
     for (part = fi->frameParts; part; part = part->next) {
-        length += part->msg->length;
+        length += Message_getLength(part->msg);
     }
 
     struct Message* out = Message_new(0, length + REQUIRED_PADDING, fi->frameAlloc);
-    Er_assert(Message_epush(out, last->bytes, last->length));
-    out->associatedFd = last->associatedFd;
+    Er_assert(Message_epush(out, last->msgbytes, Message_getLength(last)));
+    int fd = Message_getAssociatedFd(last);
     for (part = fi->frameParts; part; part = part->next) {
-        Er_assert(Message_epush(out, part->msg->bytes, part->msg->length));
-        if (!out->associatedFd) {
-            out->associatedFd = part->msg->associatedFd;
+        Er_assert(Message_epush(out, part->msg->msgbytes, Message_getLength(part->msg)));
+        if (fd == -1) {
+            fd = Message_getAssociatedFd(part->msg);
         }
     }
-
-    Assert_true(length <= out->length);
+    if (fd > -1) {
+        Message_setAssociatedFd(out, fd);
+    }
+    Assert_true(length <= Message_getLength(out));
     return out;
 }
 
@@ -79,11 +81,11 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* streamIf)
     if (fi->bytesRemaining > fi->maxMessageSize) {
         // Oversize message
         Assert_ifTesting(0);
-        return Error(OVERSIZE_MESSAGE);
+        return Error(msg, "OVERSIZE_MESSAGE");
     }
 
     if (fi->frameParts) {
-        if (fi->bytesRemaining <= (uint32_t)msg->length) {
+        if (fi->bytesRemaining <= (uint32_t)Message_getLength(msg)) {
             struct Message* wholeMessage = mergeMessage(fi, msg);
             fi->bytesRemaining = 0;
             fi->frameParts = NULL;
@@ -93,23 +95,23 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* streamIf)
             // Run the message through again since it's almost certainly not perfect size.
             Iface_CALL(receiveMessage, wholeMessage, streamIf);
             Allocator_free(frameAlloc);
-            return Error(NONE);
+            return NULL;
         }
-        fi->bytesRemaining -= msg->length;
-        Allocator_adopt(fi->frameAlloc, msg->alloc);
+        fi->bytesRemaining -= Message_getLength(msg);
+        Allocator_adopt(fi->frameAlloc, Message_getAlloc(msg));
         struct MessageList* parts = Allocator_calloc(fi->frameAlloc, sizeof(struct MessageList), 1);
         parts->msg = msg;
         parts->next = fi->frameParts;
         fi->frameParts = parts;
-        return Error(NONE);
+        return NULL;
     }
 
     for (;;) {
         while (fi->headerIndex < 4) {
-            if (!msg->length) {
-                return Error(NONE);
+            if (!Message_getLength(msg)) {
+                return NULL;
             }
-            fi->header.bytes[fi->headerIndex] = msg->bytes[0];
+            fi->header.bytes[fi->headerIndex] = msg->msgbytes[0];
             Er_assert(Message_eshift(msg, -1));
             fi->headerIndex++;
         }
@@ -119,18 +121,18 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* streamIf)
         if (fi->bytesRemaining > fi->maxMessageSize) {
             // oversize
             Assert_ifTesting(0);
-            return Error(OVERSIZE_MESSAGE);
+            return Error(msg, "OVERSIZE_MESSAGE");
         }
 
-        if (fi->bytesRemaining == (uint32_t)msg->length) {
+        if (fi->bytesRemaining == (uint32_t)Message_getLength(msg)) {
             fi->bytesRemaining = 0;
             return Iface_next(&fi->messageIf, msg);
 
-        } else if (fi->bytesRemaining < (uint32_t)msg->length) {
-            struct Allocator* alloc = Allocator_child(msg->alloc);
+        } else if (fi->bytesRemaining < (uint32_t)Message_getLength(msg)) {
+            struct Allocator* alloc = Allocator_child(Message_getAlloc(msg));
             struct Message* m = Message_new(fi->bytesRemaining, REQUIRED_PADDING, alloc);
-            m->associatedFd = msg->associatedFd;
-            Bits_memcpy(m->bytes, msg->bytes, fi->bytesRemaining);
+            Message_setAssociatedFd(m, Message_getAssociatedFd(msg));
+            Bits_memcpy(m->msgbytes, msg->msgbytes, fi->bytesRemaining);
             Er_assert(Message_eshift(msg, -fi->bytesRemaining));
             fi->bytesRemaining = 0;
             Iface_send(&fi->messageIf, m);
@@ -139,21 +141,17 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* streamIf)
 
         } else {
             fi->frameAlloc = Allocator_child(fi->alloc);
-            struct Message* m = Allocator_calloc(fi->frameAlloc, sizeof(struct Message), 1);
-            m->associatedFd = msg->associatedFd;
-            m->capacity = m->length = msg->length + 4;
-            m->bytes = Allocator_calloc(fi->frameAlloc, m->length, 1);
-            m->alloc = fi->frameAlloc;
-            Er_assert(Message_eshift(m, -m->length));
-            Er_assert(Message_epush(m, msg->bytes, msg->length));
+            struct Message* m = Message_new(0, Message_getLength(msg) + 4, fi->frameAlloc);
+            Message_setAssociatedFd(m, Message_getAssociatedFd(msg));
+            Er_assert(Message_epush(m, msg->msgbytes, Message_getLength(msg)));
             Er_assert(Message_epush(m, fi->header.bytes, 4));
 
-            fi->bytesRemaining -= msg->length;
+            fi->bytesRemaining -= Message_getLength(msg);
             fi->frameParts = Allocator_calloc(fi->frameAlloc, sizeof(struct MessageList), 1);
             fi->frameParts->msg = m;
             fi->frameParts->next = NULL;
         }
-        return Error(NONE);
+        return NULL;
     }
 }
 
@@ -161,7 +159,7 @@ static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* messageIf)
 {
     struct FramingIface_pvt* fi =
         Identity_containerOf(messageIf, struct FramingIface_pvt, messageIf);
-    Er_assert(Message_epush32be(msg, msg->length));
+    Er_assert(Message_epush32be(msg, Message_getLength(msg)));
     return Iface_next(&fi->streamIf, msg);
 }
 

+ 12 - 2
interface/Iface.c

@@ -13,15 +13,25 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 #include "interface/Iface.h"
-#include "interface/Iface.h"
 #include "memory/Allocator.h"
 #include "util/Identity.h"
+#include "wire/Error.h"
+
+void Iface_setIdentity(struct Iface* iface)
+{
+    Identity_set(iface);
+}
+
+void Iface_checkIdentity(struct Iface* iface)
+{
+    Identity_check(iface);
+}
 
 // This needs to be in a C file in order to be accessible from Rust
 Iface_DEFUN Iface_incomingFromRust(struct Message* message, struct Iface* thisInterface)
 {
     if (!thisInterface->connectedIf) {
-        return Error(INTERNAL);
+        return Error(message, "No connected interface");
     }
     return Iface_send(thisInterface, message);
 }

+ 19 - 9
interface/Iface.h

@@ -17,9 +17,10 @@
 
 #include <stdint.h>
 
-#include "wire/Error.h"
+#include "rust/cjdns_sys/RTypes.h"
 #include "wire/Message.h"
 #include "util/Defined.h"
+#include "util/Identity.h"
 #include "util/Linker.h"
 Linker_require("interface/Iface.c")
 
@@ -29,11 +30,11 @@ struct Iface;
  * @param thisInterface the interface which contains the sendMessage function pointer.
  * @param message the message
  */
-typedef struct Error_s (* Iface_Callback)(struct Message* message, struct Iface* thisInterface);
+typedef struct RTypes_Error_t* (* Iface_Callback)(struct Message* message, struct Iface* thisInterface);
 
-#define Iface_DEFUN __attribute__ ((warn_unused_result)) struct Error_s
+#define Iface_DEFUN __attribute__ ((warn_unused_result)) struct RTypes_Error_t*
 
-typedef struct Iface
+struct Iface
 {
     /** Send a message through this interface. */
     Iface_Callback send;
@@ -45,11 +46,16 @@ typedef struct Iface
 
     /** Interface to which this one is connected (if connected) */
     struct Iface* connectedIf;
-} Iface_t;
+
+    Identity
+} /* Iface_t defined in RffiPrefix.h */;
 
 // This needs to be in a C file in order to be accessible from Rust
 Iface_DEFUN Iface_incomingFromRust(struct Message* message, struct Iface* thisInterface);
 
+void Iface_setIdentity(struct Iface* iface);
+void Iface_checkIdentity(struct Iface* iface);
+
 /**
  * Send a message to an Iface.
  * Whatever interface has been *plumbed* to this interface using Iface_plumb() will receive
@@ -58,9 +64,11 @@ Iface_DEFUN Iface_incomingFromRust(struct Message* message, struct Iface* thisIn
  * assertion error, in order to forward the message which you received, you must use Iface_next()
  * and it must be a tail-call.
  */
-static inline struct Error_s Iface_send(struct Iface* iface, struct Message* msg)
+static inline struct RTypes_Error_t* Iface_send(struct Iface* iface, struct Message* msg)
 {
+    Iface_checkIdentity(iface);
     struct Iface* conn = iface->connectedIf;
+    Iface_checkIdentity(conn);
 
     #ifdef PARANOIA
         Assert_true(conn);
@@ -71,7 +79,7 @@ static inline struct Error_s Iface_send(struct Iface* iface, struct Message* msg
         conn->currentMsg = msg;
     #endif
 
-    struct Error_s ret = conn->send(msg, conn);
+    struct RTypes_Error_t* ret = conn->send(msg, conn);
 
     #ifdef PARANOIA
         msg->currentIface = NULL;
@@ -100,7 +108,7 @@ static inline Iface_DEFUN Iface_next(struct Iface* iface, struct Message* msg)
         conn->currentMsg = NULL;
     #endif
 
-    struct Error_s ret = Iface_send(iface, msg);
+    struct RTypes_Error_t* ret = Iface_send(iface, msg);
 
     #ifdef PARANOIA
         conn->currentMsg = currentMsg;
@@ -128,7 +136,7 @@ static inline Iface_DEFUN Iface_next(struct Iface* iface, struct Message* msg)
             Assert_true(!msg->currentIface);                \
             struct Iface Iface_y = { .currentMsg = msg };   \
             msg->currentIface = &Iface_y;                   \
-            struct Error_s ret = func(msg, __VA_ARGS__); \
+            struct RTypes_Error_t* ret = func(msg, __VA_ARGS__); \
             msg->currentIface = NULL;                       \
             ret; \
         }))
@@ -141,6 +149,8 @@ static inline void Iface_plumb(struct Iface* a, struct Iface* b)
 {
     Assert_true(!a->connectedIf);
     Assert_true(!b->connectedIf);
+    Iface_setIdentity(a);
+    Iface_setIdentity(b);
     a->connectedIf = b;
     b->connectedIf = a;
 }

+ 33 - 36
interface/UDPInterface.c

@@ -12,12 +12,16 @@
  * 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 "util/events/libuv/UvWrapper.h"
+#include "rust/cjdns_sys/Rffi.h"
 #include "benc/StringList.h"
 #include "interface/UDPInterface.h"
 #include "wire/Message.h"
 #include "util/events/UDPAddrIface.h"
 #include "util/GlobalConfig.h"
+#include "wire/Error.h"
+
+#include <netinet/in.h>
+#include <string.h>
 
 #define ArrayList_TYPE struct Sockaddr
 #define ArrayList_NAME Sockaddr
@@ -50,18 +54,17 @@ struct UDPInterface_pvt
 
 static struct Sockaddr* mkBcastAddr(
     uint16_t beaconPort_be,
-    uv_interface_address_t* iface,
+    Rffi_NetworkInterface* iface,
     struct Allocator* alloc)
 {
+    uint32_t addr; memcpy(&addr, iface->address.octets, 4);
+    uint32_t nmAddr; memcpy(&nmAddr, iface->address.netmask, 4);
+
     struct sockaddr_in bcast4 = {
         .sin_family = AF_INET,
         .sin_port = beaconPort_be,
         .sin_addr = {
-            .s_addr =
-                (
-                    iface->address.address4.sin_addr.s_addr &
-                    iface->netmask.netmask4.sin_addr.s_addr
-                ) | ~iface->netmask.netmask4.sin_addr.s_addr
+            .s_addr = ( addr & nmAddr ) | ~nmAddr
         }
     };
     return Sockaddr_fromNative(&bcast4, sizeof(struct sockaddr_in), alloc);
@@ -74,13 +77,10 @@ static int updateBcastAddrs(struct UDPInterface_pvt* ctx)
         String* iface = StringList_get(ctx->bcastIfaces, i);
         if (String_equals(iface, String_CONST("all"))) { all = true; }
     }
-    uv_interface_address_t* interfaces;
-    int count;
-    int res = uv_interface_addresses(&interfaces, &count);
-    if (res) {
-        Log_info(ctx->log, "uv_interface_addresses failed [%s]", uv_strerror(-res));
-        return -1;
-    }
+
+    struct Allocator* tmpAlloc = Allocator_child(ctx->allocator);
+    Rffi_NetworkInterface* interfaces;
+    int count = Rffi_interface_addresses(&interfaces, tmpAlloc);
 
     if (ctx->bcastAddrAlloc) { Allocator_free(ctx->bcastAddrAlloc); }
     struct Allocator* alloc = ctx->bcastAddrAlloc = Allocator_child(ctx->allocator);
@@ -90,7 +90,7 @@ static int updateBcastAddrs(struct UDPInterface_pvt* ctx)
 
     for (int i = 0; i < count; i++) {
         if (interfaces[i].is_internal) { continue; }
-        if (interfaces[i].address.address4.sin_family != AF_INET) { continue; }
+        if (interfaces[i].address.is_ipv6) { continue; }
         if (tunDev && !CString_strncmp(interfaces[i].name, tunDev->bytes, tunDev->len)) {
             continue;
         }
@@ -107,7 +107,7 @@ static int updateBcastAddrs(struct UDPInterface_pvt* ctx)
         }
         ArrayList_Sockaddr_add(ctx->bcastAddrs, addr);
     }
-    uv_free_interface_addresses(interfaces, count);
+    Allocator_free(tmpAlloc);
     return 0;
 }
 
@@ -116,15 +116,15 @@ static Iface_DEFUN sendPacket(struct Message* m, struct Iface* iface)
     struct UDPInterface_pvt* ctx =
         Identity_containerOf(iface, struct UDPInterface_pvt, pub.generic.iface);
 
-    Assert_true(m->length > Sockaddr_OVERHEAD);
-    struct Sockaddr* sa = (struct Sockaddr*) m->bytes;
-    Assert_true(m->length > sa->addrLen);
+    Assert_true(Message_getLength(m) > Sockaddr_OVERHEAD);
+    struct Sockaddr* sa = (struct Sockaddr*) m->msgbytes;
+    Assert_true(Message_getLength(m) > sa->addrLen);
 
     // Regular traffic
     if (!(sa->flags & Sockaddr_flags_BCAST)) { return Iface_next(&ctx->commSock, m); }
 
     if (updateBcastAddrs(ctx)) {
-        return Error(INTERNAL);
+        return Error(m, "updateBcastAddrs check logs");
     }
 
     // bcast
@@ -146,7 +146,7 @@ static Iface_DEFUN sendPacket(struct Message* m, struct Iface* iface)
         Allocator_free(tmpAlloc);
     }
 
-    return Error(NONE);
+    return NULL;
 }
 
 static Iface_DEFUN fromCommSock(struct Message* m, struct Iface* iface)
@@ -161,16 +161,16 @@ static Iface_DEFUN fromBcastSock(struct Message* m, struct Iface* iface)
     struct UDPInterface_pvt* ctx =
         Identity_containerOf(iface, struct UDPInterface_pvt, bcastSock);
 
-    if (m->length < UDPInterface_BroadcastHeader_SIZE + Sockaddr_OVERHEAD) {
+    if (Message_getLength(m) < UDPInterface_BroadcastHeader_SIZE + Sockaddr_OVERHEAD) {
         Log_debug(ctx->log, "DROP runt bcast");
-        return Error(RUNT);
+        return Error(m, "RUNT bcast");
     }
 
     struct Sockaddr_storage ss;
     Er_assert(Message_epop(m, &ss, Sockaddr_OVERHEAD));
-    if (m->length < UDPInterface_BroadcastHeader_SIZE + ss.addr.addrLen - Sockaddr_OVERHEAD) {
+    if (Message_getLength(m) < UDPInterface_BroadcastHeader_SIZE + ss.addr.addrLen - Sockaddr_OVERHEAD) {
         Log_debug(ctx->log, "DROP runt bcast");
-        return Error(RUNT);
+        return Error(m, "RUNT bcast");
     }
     Er_assert(Message_epop(m, &ss.nativeAddr, ss.addr.addrLen - Sockaddr_OVERHEAD));
 
@@ -180,17 +180,17 @@ static Iface_DEFUN fromBcastSock(struct Message* m, struct Iface* iface)
     if (hdr.fffffffc_be != Endian_hostToBigEndian32(0xfffffffc)) {
         Log_debug(ctx->log, "DROP bcast bad magic, expected 0xfffffffc got [%08x]",
             Endian_bigEndianToHost32(hdr.fffffffc_be));
-        return Error(INVALID);
+        return Error(m, "INVALID bcast, bad magic");
     }
 
     if (hdr.version != UDPInterface_CURRENT_VERSION) {
         Log_debug(ctx->log, "DROP bcast bad version [%u]", hdr.version);
-        return Error(INVALID);
+        return Error(m, "INVALID bcast, bad version");
     }
 
     if (hdr.zero) {
         Log_debug(ctx->log, "DROP bcast malformed (zero not zero)");
-        return Error(INVALID);
+        return Error(m, "INVALID bcast, hdr.zero isn't 0");
     }
 
     uint16_t commPort = Endian_bigEndianToHost16(hdr.commPort_be);
@@ -252,18 +252,15 @@ Er_DEFUN(struct UDPInterface* UDPInterface_new(struct EventBase* eventBase,
 
 Er_DEFUN(List* UDPInterface_listDevices(struct Allocator* alloc))
 {
-    List* out = List_new(alloc);
-    uv_interface_address_t* interfaces;
-    int count;
-    int res = uv_interface_addresses(&interfaces, &count);
-    if (res) { Er_raise(alloc, "uv_interface_addresses failed [%s]", uv_strerror(-res)); }
+    Rffi_NetworkInterface* interfaces;
+    int count = Rffi_interface_addresses(&interfaces, alloc);
 
+    List* out = List_new(alloc);
     for (int i = 0; i < count; i++) {
         if (interfaces[i].is_internal) { continue; }
-        if (interfaces[i].address.address4.sin_family != AF_INET) { continue; }
+        if (interfaces[i].address.is_ipv6) { continue; }
         List_addString(out, String_new(interfaces[i].name, alloc), alloc);
     }
-    uv_free_interface_addresses(interfaces, count);
     Er_ret(out);
 }
 
@@ -318,4 +315,4 @@ int UDPInterface_getFd(struct UDPInterface* udpif)
 {
     struct UDPInterface_pvt* ctx = Identity_check((struct UDPInterface_pvt*) udpif);
     return UDPAddrIface_getFd(ctx->commIf);
-}
+}

+ 6 - 2
interface/UDPInterface_admin.c

@@ -75,6 +75,9 @@ static void beginConnection(Dict* args,
     String* publicKey = Dict_getStringC(args, "publicKey");
     String* address = Dict_getStringC(args, "address");
     String* peerName = Dict_getStringC(args, "peerName");
+    int64_t* versionP = Dict_getIntC(args, "version");
+    int version = Version_DEFAULT_ASSUMPTION;
+    if (versionP) { version = *versionP; }
     char* error = NULL;
 
     Log_debug(ctx->logger, "Peering with [%s]", publicKey->bytes);
@@ -111,7 +114,7 @@ static void beginConnection(Dict* args,
         }
 
         int ret = InterfaceController_bootstrapPeer(
-            ctx->ic, ifNum, pkBytes, addr, password, login, peerName, ctx->alloc);
+            ctx->ic, ifNum, pkBytes, addr, password, login, peerName, version);
 
         Allocator_free(tempAlloc);
 
@@ -359,7 +362,8 @@ void UDPInterface_admin_register(struct EventBase* base,
             { .name = "publicKey", .required = 1, .type = "String" },
             { .name = "address", .required = 1, .type = "String" },
             { .name = "login", .required = 0, .type = "String" },
-            { .name = "peerName", .required = 0, .type = "String" }
+            { .name = "peerName", .required = 0, .type = "String" },
+            { .name = "version", .required = 0, .type = "Int" },
         }), admin);
 
     Admin_registerFunction("UDPInterface_listDevices", listDevices, ctx, true, NULL, admin);

+ 1 - 1
interface/addressable/AddrIface.h

@@ -48,7 +48,7 @@ static inline Er_DEFUN(void AddrIface_pushAddr(struct Message* msg, struct Socka
 
 static inline Er_DEFUN(struct Sockaddr* AddrIface_popAddr(struct Message* msg))
 {
-    struct Sockaddr* out = (struct Sockaddr*) msg->bytes;
+    struct Sockaddr* out = (struct Sockaddr*) msg->msgbytes;
     uint16_t len = Er(Message_epop16h(msg));
     Er(Message_epop(msg, NULL, len - 2));
     Er_ret(out);

+ 6 - 5
interface/addressable/AddrIfaceMuxer.c

@@ -18,6 +18,7 @@
 #include "util/Assert.h"
 #include "util/Identity.h"
 #include "wire/Message.h"
+#include "wire/Error.h"
 
 #include "util/Hex.h"
 
@@ -61,7 +62,7 @@ static Iface_DEFUN incomingFromAddrIf(struct Message* msg, struct Iface* addrIf)
     int idx = Map_Ifaces_indexForHandle(handle, &ctx->ifaces);
     if (idx < 0) {
         Log_info(ctx->log, "DROP message to nonexistant iface [0x%x]", handle);
-        return Error(UNHANDLED);
+        return Error(msg, "UNHANDLED (no such iface)");
     }
     return Iface_next(&ctx->ifaces.values[idx]->iface, msg);
 }
@@ -71,16 +72,16 @@ static Iface_DEFUN incomingFromInputIf(struct Message* msg, struct Iface* inputI
     struct AddrIfaceMuxer_Iface* cli =
         Identity_containerOf(inputIf, struct AddrIfaceMuxer_Iface, iface);
     struct AddrIfaceMuxer_pvt* ctx = Identity_check(cli->muxer);
-    if (msg->length < (int)sizeof(struct Sockaddr)) {
+    if (Message_getLength(msg) < (int)sizeof(struct Sockaddr)) {
         Log_info(ctx->log, "DROP runt");
-        return Error(RUNT);
+        return Error(msg, "RUNT");
     }
 
-    uint16_t addrLen = Bits_get16(msg->bytes);
+    uint16_t addrLen = Bits_get16(msg->msgbytes);
     Er_assert(AddrIface_pushAddr(msg, &cli->addr));
 
     // After pushing the address, tweak the length
-    Bits_put16(msg->bytes, cli->addr.addrLen + addrLen);
+    Bits_put16(msg->msgbytes, cli->addr.addrLen + addrLen);
 
     return Iface_next(&ctx->pub.iface.iface, msg);
 }

+ 10 - 10
interface/addressable/PacketHeaderToUDPAddrIface.c

@@ -40,7 +40,7 @@ static Iface_DEFUN incomingFromUdpIf(struct Message* message, struct Iface* udpI
     struct Headers_UDPHeader udp;
     udp.srcPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(context->pub.udpIf.addr));
     udp.destPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(addr));
-    udp.length_be = Endian_hostToBigEndian16(message->length + Headers_UDPHeader_SIZE);
+    udp.length_be = Endian_hostToBigEndian16(Message_getLength(message) + Headers_UDPHeader_SIZE);
     udp.checksum_be = 0;
     Er_assert(Message_epush(message, &udp, sizeof(struct Headers_UDPHeader)));
 
@@ -48,7 +48,7 @@ static Iface_DEFUN incomingFromUdpIf(struct Message* message, struct Iface* udpI
         .nextHeader = 17,
         .hopLimit = 255,
     };
-    ip.payloadLength_be = Endian_hostToBigEndian16(message->length);
+    ip.payloadLength_be = Endian_hostToBigEndian16(Message_getLength(message));
     Headers_setIpVersion(&ip);
     uint8_t* addrPtr = NULL;
     Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16);
@@ -56,8 +56,8 @@ static Iface_DEFUN incomingFromUdpIf(struct Message* message, struct Iface* udpI
     Assert_true(Sockaddr_getAddress(context->pub.udpIf.addr, &addrPtr) == 16);
     Bits_memcpy(ip.sourceAddr, addrPtr, 16);
 
-    uint16_t checksum_be = Checksum_udpIp6_be(ip.sourceAddr, message->bytes, message->length);
-    ((struct Headers_UDPHeader*)message->bytes)->checksum_be = checksum_be;
+    uint16_t checksum_be = Checksum_udpIp6_be(ip.sourceAddr, message->msgbytes, Message_getLength(message));
+    ((struct Headers_UDPHeader*)message->msgbytes)->checksum_be = checksum_be;
 
     Er_assert(Message_epush(message, &ip, sizeof(struct Headers_IP6Header)));
 
@@ -70,19 +70,19 @@ static Iface_DEFUN incomingFromHeaderIf(struct Message* message, struct Iface* i
         Identity_check((struct PacketHeaderToUDPAddrIface_pvt*)
             ((uint8_t*)(iface) - offsetof(struct PacketHeaderToUDPAddrIface, headerIf)));
 
-    if (message->length < Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE) {
+    if (Message_getLength(message) < Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE) {
         // runt
-        return Error(RUNT);
+        return Error(message, "RUNT");
     }
 
-    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes;
+    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->msgbytes;
 
     // udp
     if (ip->nextHeader != 17) {
-        return Error(INVALID);
+        return Error(message, "INVALID (not UDP)");
     }
 
-    struct Allocator* alloc = Allocator_child(message->alloc);
+    struct Allocator* alloc = Allocator_child(Message_getAlloc(message));
     struct Sockaddr* addr = Sockaddr_clone(context->pub.udpIf.addr, alloc);
     uint8_t* addrPtr = NULL;
     Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16);
@@ -93,7 +93,7 @@ static Iface_DEFUN incomingFromHeaderIf(struct Message* message, struct Iface* i
 
     if (Sockaddr_getPort(context->pub.udpIf.addr) != Endian_bigEndianToHost16(udp->destPort_be)) {
         // not the right port
-        return Error(INVALID);
+        return Error(message, "INVALID port");
     }
 
     Er_assert(Message_eshift(message, -(Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE)));

+ 12 - 12
interface/test/FramingIface_fuzz_test.c

@@ -36,28 +36,28 @@ static Iface_DEFUN ifaceRecvMsg(struct Message* message, struct Iface* thisInter
 {
     struct Context* ctx = Identity_containerOf(thisInterface, struct Context, iface);
     Assert_true(!ctx->success);
-    Assert_true(message->length == ctx->messageLen);
-    Assert_true(ctx->buf->length == 0);
-    Assert_true(!Bits_memcmp(ctx->bufPtr, message->bytes, ctx->messageLen));
+    Assert_true(Message_getLength(message) == ctx->messageLen);
+    Assert_true(Message_getLength(ctx->buf) == 0);
+    Assert_true(!Bits_memcmp(ctx->bufPtr, message->msgbytes, ctx->messageLen));
     ctx->success = 1;
-    return Error(NONE);
+    return NULL;
 }
 
 void CJDNS_FUZZ_MAIN(void* vctx, struct Message* fuzz)
 {
     struct Context* ctx = Identity_check((struct Context*) vctx);
-    if (fuzz->length <= 2) { return; }
+    if (Message_getLength(fuzz) <= 2) { return; }
     ctx->messageLen = Er_assert(Message_epop16be(fuzz)) % BUF_SZ;
-    ctx->buf->length = ctx->messageLen;
+    Er_assert(Message_truncate(ctx->buf, ctx->messageLen));
     Er_assert(Message_epush32be(ctx->buf, ctx->messageLen));
     for (int i = 0; ; i++) {
-        uint8_t len = fuzz->bytes[i % fuzz->length] + 1;
-        if (len > ctx->buf->length) {
-            len = ctx->buf->length;
+        uint8_t len = fuzz->msgbytes[i % Message_getLength(fuzz)] + 1;
+        if (len > Message_getLength(ctx->buf)) {
+            len = Message_getLength(ctx->buf);
         }
         struct Allocator* a = Allocator_child(ctx->alloc);
         struct Message* m = Message_new(len, 0, a);
-        Er_assert(Message_epop(ctx->buf, m->bytes, len));
+        Er_assert(Message_epop(ctx->buf, m->msgbytes, len));
         Iface_send(&ctx->outer, m);
         Allocator_free(a);
         if (ctx->success) {
@@ -74,8 +74,8 @@ void* CJDNS_FUZZ_INIT(struct Allocator* alloc, struct Random* rand)
     Iface_plumb(&ctx->iface, ctx->fi);
     ctx->alloc = alloc;
     ctx->buf = Message_new(BUF_SZ, 4, alloc);
-    Random_bytes(rand, ctx->buf->bytes, BUF_SZ);
-    ctx->bufPtr = ctx->buf->bytes;
+    Random_bytes(rand, ctx->buf->msgbytes, BUF_SZ);
+    ctx->bufPtr = ctx->buf->msgbytes;
     Identity_set(ctx);
     return ctx;
 }

+ 2 - 2
interface/test/RustIface_test.c

@@ -60,7 +60,7 @@ static Iface_DEFUN sendOutside(struct Message* msg, struct Iface* outside)
     Assert_true(top == 0x00000800);
     Assert_true(!(ctx->received & 1));
     ctx->received |= 1;
-    return Error(NONE);
+    return NULL;
 }
 
 static Iface_DEFUN sendInside(struct Message* msg, struct Iface* inside)
@@ -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);
 

+ 3 - 3
interface/tuntap/ARPServer.c

@@ -58,8 +58,8 @@ static Iface_DEFUN answerARP(struct Message* msg, struct ARPServer_pvt* as)
 {
     struct ARPHeader_6_4 arp;
     Er_assert(Message_epop(msg, &arp, ARPHeader_6_4_SIZE));
-    if (msg->length) {
-        Log_warn(as->log, "%d extra bytes in ARP, weird", msg->length);
+    if (Message_getLength(msg)) {
+        Log_warn(as->log, "%d extra bytes in ARP, weird", Message_getLength(msg));
     }
     // Swap sender with target.
     // 10 = Eth_Len + IP4_Len
@@ -84,7 +84,7 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* external)
 {
     struct ARPServer_pvt* as = Identity_containerOf(external, struct ARPServer_pvt, external);
     // Length should be ARP + Ethertype
-    if (msg->length >= ARPHeader_6_4_SIZE + 4) {
+    if (Message_getLength(msg) >= ARPHeader_6_4_SIZE + 4) {
         uint16_t ethertype = Er_assert(TUNMessageType_pop(msg));
         if (ethertype == Ethernet_TYPE_ARP) {
             if (isValidARP(msg)) {

+ 6 - 6
interface/tuntap/AndroidWrapper.c

@@ -43,10 +43,10 @@ Iface_DEFUN AndroidWrapper_incomingFromWire(struct Message* msg, struct Iface* e
 
     if (!ctx->pub.internalIf.connectedIf) {
         Log_debug(ctx->logger, "DROP message for android tun not inited");
-        return Error(UNHANDLED);
+        return Error(msg, "UNHANDLED");
     }
 
-    int version = Headers_getIpVersion(msg->bytes);
+    int version = Headers_getIpVersion(msg->msgbytes);
     uint16_t ethertype = 0;
     if (version == 4) {
         ethertype = Ethernet_TYPE_IP4;
@@ -54,12 +54,12 @@ Iface_DEFUN AndroidWrapper_incomingFromWire(struct Message* msg, struct Iface* e
         ethertype = Ethernet_TYPE_IP6;
     } else {
         Log_debug(ctx->logger, "Message is not IP/IPv6, dropped.");
-        return Error(INVALID);
+        return Error(msg, "INVALID not IP");
     }
 
     Er_assert(Message_eshift(msg, 4));
-    ((uint16_t*) msg->bytes)[0] = 0;
-    ((uint16_t*) msg->bytes)[1] = ethertype;
+    ((uint16_t*) msg->msgbytes)[0] = 0;
+    ((uint16_t*) msg->msgbytes)[1] = ethertype;
 
     return Iface_next(&ctx->pub.internalIf, msg);
 }
@@ -71,7 +71,7 @@ Iface_DEFUN AndroidWrapper_incomingFromUs(struct Message* msg, struct Iface* int
 
     if (!ctx->pub.externalIf.connectedIf) {
         Log_debug(ctx->logger, "DROP message for android tun not inited");
-        return Error(UNHANDLED);
+        return Error(msg, "UNHANDLED");
     }
 
     Er_assert(Message_eshift(msg, -4));

+ 9 - 9
interface/tuntap/BSDMessageTypeWrapper.c

@@ -42,9 +42,9 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* wireSide)
     struct BSDMessageTypeWrapper_pvt* ctx =
         Identity_containerOf(wireSide, struct BSDMessageTypeWrapper_pvt, pub.wireSide);
 
-    if (msg->length < 4) { return Error(RUNT); }
+    if (Message_getLength(msg) < 4) { return Error(msg, "RUNT"); }
 
-    uint16_t afType_be = ((uint16_t*) msg->bytes)[1];
+    uint16_t afType_be = ((uint16_t*) msg->msgbytes)[1];
     uint16_t ethertype = 0;
     if (afType_be == ctx->afInet_be) {
         ethertype = Ethernet_TYPE_IP4;
@@ -53,10 +53,10 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* wireSide)
     } else {
         Log_debug(ctx->logger, "Message of unhandled aftype [0x%04x]",
                   Endian_bigEndianToHost16(afType_be));
-        return Error(INVALID);
+        return Error(msg, "INVALID");
     }
-    ((uint16_t*) msg->bytes)[0] = 0;
-    ((uint16_t*) msg->bytes)[1] = ethertype;
+    ((uint16_t*) msg->msgbytes)[0] = 0;
+    ((uint16_t*) msg->msgbytes)[1] = ethertype;
 
     return Iface_next(&ctx->pub.inside, msg);
 }
@@ -66,9 +66,9 @@ static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* inside)
     struct BSDMessageTypeWrapper_pvt* ctx =
         Identity_containerOf(inside, struct BSDMessageTypeWrapper_pvt, pub.inside);
 
-    Assert_true(msg->length >= 4);
+    Assert_true(Message_getLength(msg) >= 4);
 
-    uint16_t ethertype = ((uint16_t*) msg->bytes)[1];
+    uint16_t ethertype = ((uint16_t*) msg->msgbytes)[1];
     uint16_t afType_be = 0;
     if (ethertype == Ethernet_TYPE_IP6) {
         afType_be = ctx->afInet6_be;
@@ -77,8 +77,8 @@ static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* inside)
     } else {
         Assert_true(!"Unsupported ethertype");
     }
-    ((uint16_t*) msg->bytes)[0] = 0;
-    ((uint16_t*) msg->bytes)[1] = afType_be;
+    ((uint16_t*) msg->msgbytes)[0] = 0;
+    ((uint16_t*) msg->msgbytes)[1] = afType_be;
 
     return Iface_next(&ctx->pub.wireSide, msg);
 }

+ 8 - 8
interface/tuntap/NDPServer.c

@@ -43,11 +43,11 @@ struct NDPServer_pvt
 
 static bool isNeighborSolicitation(struct Message* msg, struct NDPServer_pvt* ns)
 {
-    if (msg->length < Headers_IP6Header_SIZE + NDPHeader_NeighborSolicitation_SIZE) {
+    if (Message_getLength(msg) < Headers_IP6Header_SIZE + NDPHeader_NeighborSolicitation_SIZE) {
         return false;
     }
 
-    struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) msg->bytes;
+    struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) msg->msgbytes;
     struct NDPHeader_NeighborSolicitation* sol = (struct NDPHeader_NeighborSolicitation*) &ip6[1];
 
     if (sol->oneThirtyFive != 135 || sol->zero != 0) {
@@ -76,10 +76,10 @@ static Iface_DEFUN answerNeighborSolicitation(struct Message* msg, struct NDPSer
     Er_assert(Message_epop(msg, &ip6, Headers_IP6Header_SIZE));
     struct NDPHeader_NeighborSolicitation sol;
     Er_assert(Message_epop(msg, &sol, NDPHeader_NeighborSolicitation_SIZE));
-    if (msg->length) {
+    if (Message_getLength(msg)) {
         /* Right now we ignore any ICMP options. Windows will send them. */
         Log_debug(ns->log, "%d extra bytes (ICMP options?) in neighbor solicitation",
-            msg->length);
+            Message_getLength(msg));
     }
 
     struct NDPHeader_MacOpt macOpt = {
@@ -103,10 +103,10 @@ static Iface_DEFUN answerNeighborSolicitation(struct Message* msg, struct NDPSer
     Bits_memcpy(ip6.destinationAddr, ip6.sourceAddr, 16);
     Bits_memcpy(ip6.sourceAddr, sol.targetAddr, 16);
     ip6.hopLimit = 255;
-    ip6.payloadLength_be = Endian_hostToBigEndian16(msg->length);
+    ip6.payloadLength_be = Endian_hostToBigEndian16(Message_getLength(msg));
 
-    struct NDPHeader_RouterAdvert* adv = (struct NDPHeader_RouterAdvert*) msg->bytes;
-    adv->checksum = Checksum_icmp6_be(ip6.sourceAddr, msg->bytes, msg->length);
+    struct NDPHeader_RouterAdvert* adv = (struct NDPHeader_RouterAdvert*) msg->msgbytes;
+    adv->checksum = Checksum_icmp6_be(ip6.sourceAddr, msg->msgbytes, Message_getLength(msg));
 
     Er_assert(Message_epush(msg, &ip6, sizeof(struct Headers_IP6Header)));
 
@@ -121,7 +121,7 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* external)
 {
     struct NDPServer_pvt* ns = Identity_containerOf(external, struct NDPServer_pvt, external);
 
-    if (msg->length > Headers_IP6Header_SIZE + 4) {
+    if (Message_getLength(msg) > Headers_IP6Header_SIZE + 4) {
         uint16_t ethertype = Er_assert(TUNMessageType_pop(msg));
         if (ethertype != Ethernet_TYPE_IP6) {
         } else if (isNeighborSolicitation(msg, ns)) {

+ 4 - 4
interface/tuntap/SocketWrapper.c

@@ -37,7 +37,7 @@ static Iface_DEFUN incomingFromSocket(struct Message* msg, struct Iface* externa
 
     if (!ctx->pub.internalIf.connectedIf) {
         Log_debug(ctx->logger, "DROP message for socket not inited");
-        return Error(INVALID);
+        return Error(msg, "INVALID");
     }
 
     // get ess packet type
@@ -51,7 +51,7 @@ static Iface_DEFUN incomingFromSocket(struct Message* msg, struct Iface* externa
     }
 
     // skip all other types
-    return Error(INVALID);
+    return Error(msg, "INVALID");
 }
 
 static Iface_DEFUN incomingFromUs(struct Message* msg, struct Iface* internalIf)
@@ -61,11 +61,11 @@ static Iface_DEFUN incomingFromUs(struct Message* msg, struct Iface* internalIf)
 
     if (!ctx->pub.externalIf.connectedIf) {
         Log_debug(ctx->logger, "DROP message for socket not inited");
-        return Error(INVALID);
+        return Error(msg, "INVALID");
     }
 
     // send payload length
-    Er_assert(Message_epush32be(msg, msg->length));
+    Er_assert(Message_epush32be(msg, Message_getLength(msg)));
     // mark this as a normal tun packet
     Er_assert(Message_epush8(msg, SocketWrapper_TYPE_TUN_PACKET));
 

+ 4 - 4
interface/tuntap/TAPWrapper.c

@@ -34,9 +34,9 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* external)
 {
     struct TAPWrapper_pvt* tw = Identity_containerOf(external, struct TAPWrapper_pvt, external);
 
-    if (msg->length < Ethernet_SIZE-2) {
+    if (Message_getLength(msg) < Ethernet_SIZE-2) {
         Log_debug(tw->log, "runt");
-        return Error(RUNT);
+        return Error(msg, "RUNT");
     }
 
     // wacky 14 byte headers, back off into outer-space to create the padding...
@@ -66,7 +66,7 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* external)
                 AddrTools_printMac(printedMac, eth.srcAddr);
                 Log_debug(tw->log, "DROP Packet with unexpected source MAC [%s]", printedMac);
             #endif
-            return Error(INVALID);
+            return Error(msg, "INVALID");
         }
     }
     Er_assert(TUNMessageType_push(msg, eth.ethertype));
@@ -83,7 +83,7 @@ static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* internal)
     Bits_memcpy(eth.destAddr, tw->pub.peerAddress, Ethernet_ADDRLEN);
     if (Bits_isZero(tw->pub.peerAddress, Ethernet_ADDRLEN)) {
         Log_debug(tw->log, "DROP Packet because peers MAC is not yet known");
-        return Error(INVALID);
+        return Error(msg, "INVALID");
     }
 
     Er_assert(Message_epush(msg, &eth, sizeof(struct Ethernet)));

Some files were not shown because too many files changed in this diff