Commit Graph

6206 Commits

Author SHA1 Message Date
aggstam
1bf43ef4e3 darkfid2: tests to use Darkfid as node structure 2023-07-03 15:12:47 +03:00
aggstam
a3d04e0b46 bin/darkfid2: set foundation for implementing new darkfid 2023-07-03 14:35:56 +03:00
aggstam
bca71304f9 validator: full block validation added 2023-07-01 18:54:33 +03:00
parazyd
22c405dabd net/hosts: Filter self address only if not doing localnet. 2023-06-30 19:05:57 +02:00
parazyd
2a4292c0d5 doc: Add Link to 1st consensus seminar 2023-06-30 17:44:07 +02:00
ertosns
5f44e59bb1 [research/lotterysim] bug fixed with cascade control, round primary feedback precision to .2f 2023-06-30 18:37:16 +03:00
aggstam
b122e4e19e blockchain: minor pointers cleanup
We don't want to introduce &BlockchainOverlayPtr in runtime, because we will end up with lifetime hells, and copying is cheap
2023-06-30 15:06:54 +03:00
Dastan-glitch
ef27e9932b bin/darkirc: add bots code to script/ 2023-06-30 14:42:36 +03:00
aggstam
6fa4049a1b Make Repo Great Again 2023-06-29 17:29:23 +03:00
aggstam
08cde52a93 .github/workflows: updated to use rust nightly 2023-06-29 16:54:09 +03:00
aggstam
b05fbe53cf net:hosts: fixed tests 2023-06-29 16:44:20 +03:00
aggstam
1ea8adfb28 repo: updated everything to merged stuff 2023-06-29 16:13:43 +03:00
aggstam
b4d28da805 ircd: dropped 2023-06-29 15:29:25 +03:00
aggstam
37ec871075 Missing target add command added 2023-06-29 15:27:59 +03:00
aggstam
611bd9734b Missing rustqlite bundled-sqlcipher feature added 2023-06-29 15:06:47 +03:00
aggstam
af0d261812 Makefile: fmt target added 2023-06-29 15:05:14 +03:00
aggstam
abc8290b9f Makefile: use nightly toolchain 2023-06-29 15:03:18 +03:00
aggstam
fd44b20b7a consensus/state: Removed obselete SlotCheckpoint 2023-06-29 14:40:09 +03:00
parazyd
648e0de0ed net/hosts: Verify pluggable transport address correctness. 2023-06-29 13:13:16 +02:00
parazyd
55ee919906 net: Perform full p2p code cleanup and improve certain pieces.
Notable changes:

* Rewritten transport protocols into Dialer and Listener (Nym is TODO)

  This simplifies using the transports a lot, as can be seen for example
  in src/rpc, and generally around the p2p library. It also defines features
  for each transport (all of which are enabled by default). We drop the
  socks client for Tor and Nym and use first-class support with the Arti Tor
  library, and nym-sphinx/nym-websockets (to be used with nym-client).

* Outbound session healing

  The outbound session will now poll and try to fill all the requested
  slots more efficiently, and if needed, will activate peer discovery to
  find more peers if we can't connect to any known ones. Also if we're
  unable to connect to any, we shall drop them from our set.

  Additionally, transport mixing is enabled by default, so when we're
  allowing transport mixing, and we use Tor, we will also be able to connect
  to other transports that Tor can connect to (e.g. tcp://).

* Unix socket transport dropped

  We haven't been using this, and it seems we're not going down this path,
  so the code has been obsoleted and removed.

* TLS session verification

  We fully verify server and client TLS certificates upon connection so
  we're able to perform TLS1.3 with forward secrecy.

* lilith pruning

  lilith now periodically prunes known peers from its sets if it's unable
  to connect to them.
2023-06-29 13:13:15 +02:00
parazyd
d070b7792b wallet: Replace sqlx with rusqlite. 2023-06-29 13:06:54 +02:00
parazyd
cbbfcef832 raft: Remove entire raft module.
This code is not needed anymore.
2023-06-29 13:06:54 +02:00
parazyd
761f3d508d rpc: Remove websockets client. 2023-06-29 13:06:54 +02:00
parazyd
9102fbf33c util/ringbuffer: Implement back() method. 2023-06-29 13:06:54 +02:00
parazyd
0ac5d6026b util/cli: Make -v show the [INFO] log target, and -vv to actually debug.
Also disable file logging by default.
This needs to be done through config files.
2023-06-29 13:06:54 +02:00
parazyd
1699d8e8d6 lilith: Clean up and implement periodic hosts purging.
The purging is done by attempting connections and removing the host
from the set if lilith is unable to connect and/or perform the handshake.
2023-06-29 13:06:54 +02:00
parazyd
ee2cc0e0b2 script/research: Remove arti-exp 2023-06-29 13:06:54 +02:00
parazyd
a065f0dae4 serial: Implement semver crate serialization. 2023-06-29 13:06:54 +02:00
parazyd
949b0bb1e9 net/hosts: Add onion note about Arti. 2023-06-29 13:06:54 +02:00
parazyd
672185cf44 net/tls: Implement client certificate verification.
This the same way like the previous commit 4751d2f81681230d90568610f415e0c56c3ace92
2023-06-29 13:06:54 +02:00
parazyd
ee62ec7bd2 net/tls: Implement server certificate verification.
The system works such that the server creates a new TLS certificate
from an ed25519 keypair. The public key is also encoded with base32
and placed into the altName of the certificate so it can easily be
used with other things.

The server certificate verification will parse the certificate, then
look for the altName extension, attempt to parse the public key from
there, make sure that it is the same as the actual certificate pubkey,
and finally it will verify the certificate signature.

We also remove "pem" dependencies and use binary DER encoding where
applicable.

This is a breaking change for existing deployments.

diff --git a/Cargo.lock b/Cargo.lock
index ff543ddedd..893bfa2380 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -177,6 +177,45 @@ version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8868f09ff8cea88b079da74ae569d9b8c62a23c68c746240b704ee6f7525c89c"

+[[package]]
+name = "asn1-rs"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0"
+dependencies = [
+ "asn1-rs-derive",
+ "asn1-rs-impl",
+ "displaydoc",
+ "nom",
+ "num-traits",
+ "rusticata-macros",
+ "thiserror",
+ "time 0.3.22",
+]
+
+[[package]]
+name = "asn1-rs-derive"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "synstructure",
+]
+
+[[package]]
+name = "asn1-rs-impl"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
 [[package]]
 name = "async-attributes"
 version = "1.1.2"
@@ -1332,6 +1371,7 @@ dependencies = [
  "wasmer",
  "wasmer-compiler-singlepass",
  "wasmer-middlewares",
+ "x509-parser",
 ]

 [[package]]
@@ -1735,6 +1775,20 @@ dependencies = [
  "url",
 ]

+[[package]]
+name = "der-parser"
+version = "8.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e"
+dependencies = [
+ "asn1-rs",
+ "displaydoc",
+ "nom",
+ "num-bigint",
+ "num-traits",
+ "rusticata-macros",
+]
+
 [[package]]
 name = "derivative"
 version = "2.2.0"
@@ -1829,6 +1883,17 @@ dependencies = [
  "winapi",
 ]

+[[package]]
+name = "displaydoc"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.18",
+]
+
 [[package]]
 name = "dlib"
 version = "0.5.2"
@@ -3372,6 +3437,15 @@ dependencies = [
  "cc",
 ]

+[[package]]
+name = "oid-registry"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff"
+dependencies = [
+ "asn1-rs",
+]
+
 [[package]]
 name = "once_cell"
 version = "1.18.0"
@@ -4097,6 +4171,15 @@ dependencies = [
  "semver 0.11.0",
 ]

+[[package]]
+name = "rusticata-macros"
+version = "4.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
+dependencies = [
+ "nom",
+]
+
 [[package]]
 name = "rustix"
 version = "0.37.20"
@@ -4734,6 +4817,18 @@ dependencies = [
  "unicode-ident",
 ]

+[[package]]
+name = "synstructure"
+version = "0.12.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "unicode-xid",
+]
+
 [[package]]
 name = "tabbycat"
 version = "0.1.2"
@@ -5163,6 +5258,12 @@ version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"

+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
 [[package]]
 name = "unicode_categories"
 version = "0.1.1"
@@ -5877,6 +5978,24 @@ dependencies = [
  "zeroize",
 ]

+[[package]]
+name = "x509-parser"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bab0c2f54ae1d92f4fcb99c0b7ccf0b1e3451cbd395e5f115ccbdbcb18d4f634"
+dependencies = [
+ "asn1-rs",
+ "data-encoding",
+ "der-parser",
+ "lazy_static",
+ "nom",
+ "oid-registry",
+ "ring",
+ "rusticata-macros",
+ "thiserror",
+ "time 0.3.22",
+]
+
 [[package]]
 name = "xsalsa20poly1305"
 version = "0.9.1"
diff --git a/Cargo.toml b/Cargo.toml
index 1aaf3c1641..4fb39d2603 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -77,9 +77,10 @@ ipnet = {version = "2.7.2", optional = true}
 socket2 = {version = "0.5.3", optional = true, features = ["all"]}

 # TLS cert utilities
-ed25519-compact = {version = "2.0.4", features = ["pem"], optional = true}
-rcgen = {version = "0.10.0", features = ["pem"], optional = true}
+ed25519-compact = {version = "2.0.4", optional = true}
+rcgen = {version = "0.10.0", optional = true}
 rustls-pemfile = {version = "1.0.2", optional = true}
+x509-parser = {version = "0.15.0", features = ["validate", "verify"], optional = true}

 # Encoding
 bs58 = {version = "0.5.0", optional = true}
@@ -213,6 +214,7 @@ net = [
     "rand",
     "rcgen",
     "rustls-pemfile",
+    "x509-parser",
     "serde",
     "serde_json",
     "socket2",
diff --git a/src/net/transport/upgrade_tls.rs b/src/net/transport/upgrade_tls.rs
index 570d5d3b01..8674c25938 100644
--- a/src/net/transport/upgrade_tls.rs
+++ b/src/net/transport/upgrade_tls.rs
@@ -31,9 +31,16 @@ use futures_rustls::{
     },
     TlsAcceptor, TlsConnector, TlsStream,
 };
+use log::error;
 use rustls_pemfile::pkcs8_private_keys;
+use x509_parser::{
+    extensions::{GeneralName, ParsedExtension},
+    parse_x509_certificate,
+    prelude::FromDer,
+    x509::SubjectPublicKeyInfo,
+};

-use crate::Result;
+use crate::{util::encoding::base32, Result};

 const CIPHER_SUITE: &str = "TLS13_CHACHA20_POLY1305_SHA256";

@@ -53,14 +60,82 @@ struct ServerCertificateVerifier;
 impl ServerCertVerifier for ServerCertificateVerifier {
     fn verify_server_cert(
         &self,
-        _end_entity: &Certificate,
+        end_entity: &Certificate,
         _intermediates: &[Certificate],
         _server_name: &ServerName,
         _scrs: &mut dyn Iterator<Item = &[u8]>,
         _ocsp_response: &[u8],
         _now: SystemTime,
     ) -> std::result::Result<ServerCertVerified, rustls::Error> {
-        // TODO: upsycle
+        // Parse the actual end_entity certificate
+        let Ok((_, cert)) = parse_x509_certificate(&end_entity.0) else {
+            error!(target: "net::tls", "Failed parsing server TLS certificate");
+            return Err(rustls::CertificateError::BadEncoding.into())
+        };
+
+        // We keep a public key in the altName, so we need to grab it.
+        // We compare that the actual public key of the certificate is
+        // the same as that one, and we then verify the signature of the
+        // provided certificate.
+        #[rustfmt::skip]
+        let oid = x509_parser::oid_registry::asn1_rs::oid!(2.5.29.17);
+        let Ok(Some(extension)) = cert.get_extension_unique(&oid) else {
+            error!(target: "net::tls", "Could not find OID extension for subjectAltName");
+            return Err(rustls::CertificateError::BadSignature.into())
+        };
+
+        // Parse the actual extension
+        // (ノಠ益ಠ)ノ彡┻━┻
+        let pubkey_bytes = match extension.parsed_extension() {
+            ParsedExtension::SubjectAlternativeName(altname) => {
+                if altname.general_names.len() != 1 {
+                    return Err(rustls::CertificateError::BadEncoding.into())
+                }
+
+                match altname.general_names[0] {
+                    GeneralName::DNSName(a) => base32::decode(a),
+                    _ => return Err(rustls::CertificateError::BadEncoding.into()),
+                }
+            }
+            _ => return Err(rustls::CertificateError::BadEncoding.into()),
+        };
+        let Some(pubkey_bytes) = pubkey_bytes else {
+            error!(target: "net::tls", "Could not decode server pubkey from altName");
+            return Err(rustls::CertificateError::BadSignature.into())
+        };
+        if pubkey_bytes.len() != 32 {
+            error!(target: "net::tls", "Could not decode server pubkey from altName");
+            return Err(rustls::CertificateError::BadSignature.into())
+        }
+        let pubkey_der = ed25519_compact::PublicKey::new(pubkey_bytes.try_into().unwrap()).to_der();
+        let Ok((_, parsed_pubkey)) = SubjectPublicKeyInfo::from_der(&pubkey_der) else {
+            error!(target: "net::tls", "Could not decode server pubkey from altName");
+            return Err(rustls::CertificateError::BadSignature.into())
+        };
+
+        let Ok(parsed_name_pubkey) = parsed_pubkey.parsed() else {
+            error!(target: "net::tls", "Could not parse server altName pubkey");
+            return Err(rustls::CertificateError::BadEncoding.into())
+        };
+
+        let Ok(parsed_cert_pubkey) = cert.public_key().parsed() else {
+            error!(target: "net::tls", "Could not parse server certificate pubkey");
+            return Err(rustls::CertificateError::BadEncoding.into())
+        };
+
+        if parsed_name_pubkey != parsed_cert_pubkey {
+            error!(target: "net::tls", "Server altName pubkey does not match certificate key");
+            return Err(rustls::CertificateError::BadSignature.into())
+        }
+
+        // Finally verify the signature. By passing `None`, it should use
+        // the certificate pubkey, but we also verified that it matches
+        // the one in altNames above.
+        if let Err(e) = cert.verify_signature(None) {
+            error!(target: "net::tls", "Failed verifying server certificate signature: {}", e);
+            return Err(rustls::CertificateError::BadSignature.into())
+        }
+
         Ok(ServerCertVerified::assertion())
     }
 }
@@ -92,11 +167,13 @@ pub struct TlsUpgrade {
 impl TlsUpgrade {
     pub fn new() -> Self {
         // On each instantiation, generate a new keypair and certificate.
-        let keypair_pem = ed25519_compact::KeyPair::generate().to_pem();
+        let keypair = ed25519_compact::KeyPair::generate();
+        let keypair_pem = keypair.to_pem();
         let secret_key = pkcs8_private_keys(&mut keypair_pem.as_bytes()).unwrap();
         let secret_key = rustls::PrivateKey(secret_key[0].clone());

-        let altnames = vec![String::from("dark.fi")];
+        let altname = base32::encode(false, keypair.pk.as_slice()).to_ascii_lowercase();
+        let altnames = vec![altname];
         let mut cert_params = rcgen::CertificateParams::new(altnames);
         cert_params.alg = &rcgen::PKCS_ED25519;
         cert_params.key_pair = Some(rcgen::KeyPair::from_pem(&keypair_pem).unwrap());
2023-06-29 13:06:54 +02:00
parazyd
cb4354e127 tests/network_transports: Avoid TLS EOF panic. 2023-06-29 13:06:54 +02:00
aggstam
c77ed67df1 validator: decoupled verification functions so we can chain them using same overlay 2023-06-28 20:52:29 +03:00
aggstam
97445fca25 blockchain: cleanup 2023-06-28 18:29:46 +03:00
aggstam
800adf21d9 blockchain/contract_store: added missing functions so transaction verification now operates purelly over an overlay 2023-06-28 16:04:01 +03:00
aggstam
feabf5a67a blockchain: rewrite completed
Attention: this commit breaks darkfid/faucetd network functionalities, so nodes can't sync or participate in the protocol. Wait for their rewrite(TM)
2023-06-28 14:42:14 +03:00
aggstam
f37e05e0ec validator/blockchain: added rest overlays needed for validations 2023-06-27 19:23:45 +03:00
aggstam
44be02f528 validator/blockchain/contract_store: unused import removed 2023-06-27 16:18:00 +03:00
ertosns
2e2aff3919 [reesarch/lotterysim] pool zero advantage demonestration 2023-06-27 13:56:22 +03:00
aggstam
6318c2bd76 script/research/lotterysim: .gitignore added 2023-06-27 12:20:28 +02:00
aggstam
9617331dde validator/blockchain/contract_store: reverted ContractStateStore::remove() since drop_tree() doesn't work in an atomic transaction 2023-06-27 12:20:28 +02:00
aggstam
92b9b339f4 validatro/blockchain/contract_store: make ContractStateStore::remove atomic 2023-06-27 12:38:49 +03:00
Dastan-glitch
64abd7db65 bin/tau: show info on one id instead of listing it 2023-06-27 05:28:31 +03:00
Dastan-glitch
5ec6f86e07 book: update tau doc 2023-06-27 05:12:56 +03:00
Dastan-glitch
8363c4c891 bin/tau: update cli help message 2023-06-27 05:11:05 +03:00
Dastan-glitch
d08c45045d bin/tau: change assign usage from key:value to @value 2023-06-27 04:48:14 +03:00
Dastan-glitch
64f3978280 bin/darkirc: minor test script rename contact 2023-06-27 04:24:02 +03:00
Dastan-glitch
194cd2e1ff book: update event_graph docs 2023-06-27 04:22:39 +03:00
aggstam
7a2f07502c WIP: validator: blockchain rewrite foundation added 2023-06-26 22:02:25 +03:00
aggstam
8401789b06 script/research/blockchain-explorer: updated to latest structs 2023-06-24 18:18:31 +03:00