diff --git a/veilid-core/src/crypto/mod.rs b/veilid-core/src/crypto/mod.rs index 07c02a37..0b2c63ec 100644 --- a/veilid-core/src/crypto/mod.rs +++ b/veilid-core/src/crypto/mod.rs @@ -325,4 +325,11 @@ impl Crypto { }, ) } + + pub(crate) fn validate_crypto_kind(kind: CryptoKind) -> VeilidAPIResult<()> { + if !VALID_CRYPTO_KINDS.contains(&kind) { + apibail_generic!("invalid crypto kind"); + } + Ok(()) + } } diff --git a/veilid-core/src/routing_table/find_peers.rs b/veilid-core/src/routing_table/find_peers.rs index c60b3537..03b109b3 100644 --- a/veilid-core/src/routing_table/find_peers.rs +++ b/veilid-core/src/routing_table/find_peers.rs @@ -13,6 +13,9 @@ impl RoutingTable { "Not finding closest peers because our network class is still invalid", ); } + if Crypto::validate_crypto_kind(key.kind).is_err() { + return NetworkResult::invalid_message("invalid crypto kind"); + } // find N nodes closest to the target node in our routing table let own_peer_info = self.get_own_peer_info(RoutingDomain::PublicInternet); @@ -46,7 +49,7 @@ impl RoutingTable { }; let own_peer_info = self.get_own_peer_info(RoutingDomain::PublicInternet); - let closest_nodes = self.find_closest_nodes( + let closest_nodes = match self.find_closest_nodes( node_count, key, filters, @@ -54,7 +57,13 @@ impl RoutingTable { |rti, entry| { rti.transform_to_peer_info(RoutingDomain::PublicInternet, &own_peer_info, entry) }, - ); + ) { + Ok(v) => v, + Err(e) => { + error!("failed to find closest nodes for key {}: {}", key, e); + return NetworkResult::invalid_message("failed to find closest nodes for key"); + } + }; NetworkResult::value(closest_nodes) } @@ -117,7 +126,7 @@ impl RoutingTable { }; // - let closest_nodes = self.find_closest_nodes( + let closest_nodes = match self.find_closest_nodes( node_count, key, filters, @@ -127,7 +136,13 @@ impl RoutingTable { e.make_peer_info(RoutingDomain::PublicInternet).unwrap() }) }, - ); + ) { + Ok(v) => v, + Err(e) => { + error!("failed to find closest nodes for key {}: {}", key, e); + return NetworkResult::invalid_message("failed to find closest nodes for key"); + } + }; // Validate peers returned are, in fact, closer to the key than the node we sent this to // This same test is used on the other side so we vet things here diff --git a/veilid-core/src/routing_table/mod.rs b/veilid-core/src/routing_table/mod.rs index a1106d83..2f63df4a 100644 --- a/veilid-core/src/routing_table/mod.rs +++ b/veilid-core/src/routing_table/mod.rs @@ -1012,7 +1012,7 @@ impl RoutingTable { node_id: TypedKey, filters: VecDeque, transform: T, - ) -> Vec + ) -> VeilidAPIResult> where T: for<'r> FnMut(&'r RoutingTableInner, Option>) -> O + Send, { diff --git a/veilid-core/src/routing_table/routing_table_inner.rs b/veilid-core/src/routing_table/routing_table_inner.rs index e82f9f9d..029f5da8 100644 --- a/veilid-core/src/routing_table/routing_table_inner.rs +++ b/veilid-core/src/routing_table/routing_table_inner.rs @@ -1162,7 +1162,7 @@ impl RoutingTableInner { node_id: TypedKey, mut filters: VecDeque, transform: T, - ) -> Vec + ) -> VeilidAPIResult> where T: for<'r> FnMut(&'r RoutingTableInner, Option>) -> O, { @@ -1170,7 +1170,9 @@ impl RoutingTableInner { // Get the crypto kind let crypto_kind = node_id.kind; - let vcrypto = self.unlocked_inner.crypto().get(crypto_kind).unwrap(); + let Some(vcrypto) = self.unlocked_inner.crypto().get(crypto_kind) else { + apibail_generic!("invalid crypto kind"); + }; // Filter to ensure entries support the crypto kind in use let filter = Box::new( @@ -1236,7 +1238,7 @@ impl RoutingTableInner { let out = self.find_peers_with_sort_and_filter(node_count, cur_ts, filters, sort, transform); log_rtab!(">> find_closest_nodes: node count = {}", out.len()); - out + Ok(out) } pub fn sort_and_clean_closest_noderefs( diff --git a/veilid-core/src/rpc_processor/fanout_call.rs b/veilid-core/src/rpc_processor/fanout_call.rs index 215378aa..7d16b086 100644 --- a/veilid-core/src/rpc_processor/fanout_call.rs +++ b/veilid-core/src/rpc_processor/fanout_call.rs @@ -208,7 +208,7 @@ where } } - fn init_closest_nodes(self: Arc) { + fn init_closest_nodes(self: Arc) -> Result<(), RPCError> { // Get the 'node_count' closest nodes to the key out of our routing table let closest_nodes = { let routing_table = self.routing_table.clone(); @@ -247,11 +247,14 @@ where NodeRef::new(routing_table.clone(), v.unwrap().clone(), None) }; - routing_table.find_closest_nodes(self.node_count, self.node_id, filters, transform) + routing_table + .find_closest_nodes(self.node_count, self.node_id, filters, transform) + .map_err(RPCError::invalid_format)? }; let mut ctx = self.context.lock(); ctx.closest_nodes = closest_nodes; + Ok(()) } pub async fn run(self: Arc) -> TimeoutOr, RPCError>> { @@ -264,7 +267,9 @@ where }; // Initialize closest nodes list - self.clone().init_closest_nodes(); + if let Err(e) = self.clone().init_closest_nodes() { + return TimeoutOr::value(Err(e)); + } // Do a quick check to see if we're already done if self.clone().evaluate_done() { diff --git a/veilid-core/src/veilid_api/api.rs b/veilid-core/src/veilid_api/api.rs index 5953a251..6c943e61 100644 --- a/veilid-core/src/veilid_api/api.rs +++ b/veilid-core/src/veilid_api/api.rs @@ -188,6 +188,10 @@ impl VeilidAPI { stability: Stability, sequencing: Sequencing, ) -> VeilidAPIResult<(RouteId, Vec)> { + for kind in crypto_kinds { + Crypto::validate_crypto_kind(*kind)?; + } + let default_route_hop_count: usize = { let config = self.config()?; let c = config.get(); diff --git a/veilid-core/src/veilid_api/routing_context.rs b/veilid-core/src/veilid_api/routing_context.rs index 16afc60a..2aeebc17 100644 --- a/veilid-core/src/veilid_api/routing_context.rs +++ b/veilid-core/src/veilid_api/routing_context.rs @@ -199,6 +199,7 @@ impl RoutingContext { kind: Option, ) -> VeilidAPIResult { let kind = kind.unwrap_or(best_crypto_kind()); + Crypto::validate_crypto_kind(kind)?; let storage_manager = self.api.storage_manager()?; storage_manager .create_record(kind, schema, self.unlocked_inner.safety_selection) @@ -213,6 +214,7 @@ impl RoutingContext { key: TypedKey, writer: Option, ) -> VeilidAPIResult { + Crypto::validate_crypto_kind(key.kind)?; let storage_manager = self.api.storage_manager()?; storage_manager .open_record(key, writer, self.unlocked_inner.safety_selection) @@ -222,6 +224,7 @@ impl RoutingContext { /// Closes a DHT record at a specific key that was opened with create_dht_record or open_dht_record. /// Closing a record allows you to re-open it with a different routing context pub async fn close_dht_record(&self, key: TypedKey) -> VeilidAPIResult<()> { + Crypto::validate_crypto_kind(key.kind)?; let storage_manager = self.api.storage_manager()?; storage_manager.close_record(key).await } @@ -230,6 +233,7 @@ impl RoutingContext { /// Deleting a record does not delete it from the network, but will remove the storage of the record /// locally, and will prevent its value from being refreshed on the network by this node. pub async fn delete_dht_record(&self, key: TypedKey) -> VeilidAPIResult<()> { + Crypto::validate_crypto_kind(key.kind)?; let storage_manager = self.api.storage_manager()?; storage_manager.delete_record(key).await } @@ -244,6 +248,7 @@ impl RoutingContext { subkey: ValueSubkey, force_refresh: bool, ) -> VeilidAPIResult> { + Crypto::validate_crypto_kind(key.kind)?; let storage_manager = self.api.storage_manager()?; storage_manager.get_value(key, subkey, force_refresh).await } @@ -257,6 +262,7 @@ impl RoutingContext { subkey: ValueSubkey, data: Vec, ) -> VeilidAPIResult> { + Crypto::validate_crypto_kind(key.kind)?; let storage_manager = self.api.storage_manager()?; storage_manager.set_value(key, subkey, data).await } @@ -273,6 +279,7 @@ impl RoutingContext { expiration: Timestamp, count: u32, ) -> VeilidAPIResult { + Crypto::validate_crypto_kind(key.kind)?; let storage_manager = self.api.storage_manager()?; storage_manager .watch_values(key, subkeys, expiration, count) @@ -286,6 +293,7 @@ impl RoutingContext { key: TypedKey, subkeys: ValueSubkeyRangeSet, ) -> VeilidAPIResult { + Crypto::validate_crypto_kind(key.kind)?; let storage_manager = self.api.storage_manager()?; storage_manager.cancel_watch_values(key, subkeys).await } diff --git a/veilid-flutter/lib/veilid_crypto.dart b/veilid-flutter/lib/veilid_crypto.dart index 6b258c11..665942ca 100644 --- a/veilid-flutter/lib/veilid_crypto.dart +++ b/veilid-flutter/lib/veilid_crypto.dart @@ -23,6 +23,7 @@ String cryptoKindToString(CryptoKind kind) => const CryptoKind bestCryptoKind = cryptoKindVLD0; Uint8List cryptoKindToBytes(CryptoKind kind) { + assert(kind == cryptoKindVLD0, 'xxx'); final b = Uint8List(4); ByteData.sublistView(b).setUint32(0, kind); return b; @@ -34,6 +35,7 @@ CryptoKind cryptoKindFromString(String s) { } final kind = ByteData.sublistView(Uint8List.fromList(s.codeUnits)).getUint32(0); + assert(kind == cryptoKindVLD0, 'xxx'); return kind; }