Commit Graph

3069 Commits

Author SHA1 Message Date
parazyd
98ef7c834e chore: Update project dependencies. 2023-07-08 20:17:47 +02:00
aggstam
77067ac615 util/cli: fmt 2023-07-08 19:05:33 +03:00
aggstam
5d63d86083 chore: cleanup 2023-07-08 19:04:47 +03:00
parazyd
363a6cd998 vanityaddr: Remove indicatif dependency. 2023-07-08 18:01:23 +02:00
parazyd
ba25b08458 net: Add a function to map DnetInfo into a JSON map. 2023-07-08 16:21:49 +02:00
parazyd
f73c9c8f61 net: dnet cleanups and improvements. 2023-07-08 16:21:49 +02:00
parazyd
021235b534 util/ringbuffer: Use const generic for size. 2023-07-08 16:21:49 +02:00
aggstam
c7b7c2dd11 contract/test-harness/vks: updated VKS_HASH 2023-07-08 15:28:29 +03:00
parazyd
281aa87faf zk/vm: Implement zero_cond opcode. 2023-07-08 11:07:07 +02:00
parazyd
f001cb05d1 zk/gadget: Implement f(a,b) = if a==0 {a} else {b} as zero_cond chip. 2023-07-07 21:49:49 +02:00
parazyd
a32b718d0d zk/gadget: Remove unused code from cond_select. 2023-07-07 21:49:49 +02:00
aggstam
17415a3d21 validator: use new pid 2023-07-07 21:05:46 +03:00
aggstam
9712efdfb1 validator/consensus/pid: sigmas caclulation foundation 2023-07-07 16:43:48 +03:00
aggstam
b21e787319 error: restore missing error 2023-07-05 16:54:00 +03:00
parazyd
a654341ea4 Remove some unnecessary dependencies. 2023-07-04 23:52:30 +02:00
x
85d837a1e7 add ping-pong timeout when remote host doesn't reply back in time. 2023-07-04 21:17:57 +02:00
aggstam
9758c6c01f repo: fixed tests 2023-07-04 17:23:20 +03:00
aggstam
a63a808992 util/cli/async_daemonize: use log_file to explicitly write to, impl signal handler using async signal hooks 2023-07-04 13:17:40 +03:00
parazyd
8b1042ce17 net/protocol/ping: Correct pong debug message. 2023-07-03 22:53:21 +02:00
parazyd
113c45b41e net/hosts: Fix scheme parsing. 2023-07-03 21:21:51 +02:00
parazyd
6c740085f5 net/settings: Default transport_mixing to false. 2023-07-03 20:57:39 +02:00
parazyd
17471d7aaa net/hosts: Remove redundant scheme handling. 2023-07-03 18:10:03 +02:00
parazyd
3546af6c79 lilith: Support versioning of spawned networks. 2023-07-03 17:35:33 +02:00
aggstam
0d00179abd darkfid2: further extend tests foundation | repo: fmt 2023-07-03 16:50:44 +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
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
aggstam
6fa4049a1b Make Repo Great Again 2023-06-29 17:29:23 +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
611bd9734b Missing rustqlite bundled-sqlcipher feature added 2023-06-29 15:06:47 +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
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