Generalize typestates, make verified valid because its more correct for Identity.

This commit is contained in:
Adam Ierymenko 2023-01-03 15:24:46 -05:00
parent 7dabeb9595
commit 382688d251
15 changed files with 76 additions and 80 deletions

View file

@ -35,7 +35,7 @@ pub struct Controller {
reaper: Reaper, reaper: Reaper,
runtime: tokio::runtime::Handle, runtime: tokio::runtime::Handle,
database: Arc<dyn Database>, database: Arc<dyn Database>,
local_identity: Verified<Identity>, local_identity: Valid<Identity>,
/// Handler for MULTICAST_LIKE and MULTICAST_GATHER messages. /// Handler for MULTICAST_LIKE and MULTICAST_GATHER messages.
multicast_authority: MulticastAuthority, multicast_authority: MulticastAuthority,
@ -256,7 +256,7 @@ impl Controller {
/// reason is returned with None or an acceptance reason with a network configuration is returned. /// reason is returned with None or an acceptance reason with a network configuration is returned.
async fn authorize( async fn authorize(
self: &Arc<Self>, self: &Arc<Self>,
source_identity: &Verified<Identity>, source_identity: &Valid<Identity>,
network_id: NetworkId, network_id: NetworkId,
time_clock: i64, time_clock: i64,
) -> Result<(AuthenticationResult, Option<NetworkConfig>), Box<dyn Error + Send + Sync>> { ) -> Result<(AuthenticationResult, Option<NetworkConfig>), Box<dyn Error + Send + Sync>> {
@ -499,14 +499,14 @@ impl Controller {
impl InnerProtocolLayer for Controller { impl InnerProtocolLayer for Controller {
#[inline(always)] #[inline(always)]
fn should_respond_to(&self, _: &Verified<Identity>) -> bool { fn should_respond_to(&self, _: &Valid<Identity>) -> bool {
// Controllers always have to establish sessions to process requests. We don't really know if // Controllers always have to establish sessions to process requests. We don't really know if
// a member is relevant until we have looked up both the network and the member, since whether // a member is relevant until we have looked up both the network and the member, since whether
// or not to "learn" unknown members is a network level option. // or not to "learn" unknown members is a network level option.
true true
} }
fn has_trust_relationship(&self, id: &Verified<Identity>) -> bool { fn has_trust_relationship(&self, id: &Valid<Identity>) -> bool {
self.recently_authorized self.recently_authorized
.read() .read()
.unwrap() .unwrap()

View file

@ -5,7 +5,7 @@ use async_trait::async_trait;
use notify::{RecursiveMode, Watcher}; use notify::{RecursiveMode, Watcher};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use zerotier_network_hypervisor::vl1::{Address, Identity, Verified}; use zerotier_network_hypervisor::vl1::{Address, Identity, Valid};
use zerotier_network_hypervisor::vl2::NetworkId; use zerotier_network_hypervisor::vl2::NetworkId;
use zerotier_utils::reaper::Reaper; use zerotier_utils::reaper::Reaper;
use zerotier_utils::tokio::fs; use zerotier_utils::tokio::fs;
@ -32,7 +32,7 @@ const EVENT_HANDLER_TASK_TIMEOUT: Duration = Duration::from_secs(10);
/// is different from V1 so it'll need a converter to use with V1 FileDb controller data. /// is different from V1 so it'll need a converter to use with V1 FileDb controller data.
pub struct FileDatabase { pub struct FileDatabase {
base_path: PathBuf, base_path: PathBuf,
local_identity: Verified<Identity>, local_identity: Valid<Identity>,
change_sender: Sender<Change>, change_sender: Sender<Change>,
tasks: Reaper, tasks: Reaper,
cache: Cache, cache: Cache,
@ -251,11 +251,11 @@ impl Drop for FileDatabase {
} }
impl VL1DataStorage for FileDatabase { impl VL1DataStorage for FileDatabase {
fn load_node_identity(&self) -> Option<Verified<Identity>> { fn load_node_identity(&self) -> Option<Valid<Identity>> {
load_node_identity(self.base_path.as_path()) load_node_identity(self.base_path.as_path())
} }
fn save_node_identity(&self, id: &Verified<Identity>) -> bool { fn save_node_identity(&self, id: &Valid<Identity>) -> bool {
save_node_identity(self.base_path.as_path(), id) save_node_identity(self.base_path.as_path(), id)
} }
} }

View file

@ -10,7 +10,7 @@ use tokio_postgres::types::Type;
use tokio_postgres::{Client, Statement}; use tokio_postgres::{Client, Statement};
use zerotier_crypto::secure_eq; use zerotier_crypto::secure_eq;
use zerotier_crypto::verified::Verified; use zerotier_crypto::typestate::Valid;
use zerotier_network_hypervisor::vl1::{Address, Identity, InetAddress}; use zerotier_network_hypervisor::vl1::{Address, Identity, InetAddress};
use zerotier_network_hypervisor::vl2::networkconfig::IpRoute; use zerotier_network_hypervisor::vl2::networkconfig::IpRoute;
@ -137,7 +137,7 @@ impl<'a> Drop for ConnectionHolder<'a> {
pub struct PostgresDatabase { pub struct PostgresDatabase {
local_controller_id_str: String, local_controller_id_str: String,
local_identity: Verified<Identity>, local_identity: Valid<Identity>,
connections: Mutex<(Vec<Box<PostgresConnection>>, Sender<()>)>, connections: Mutex<(Vec<Box<PostgresConnection>>, Sender<()>)>,
postgres_path: String, postgres_path: String,
runtime: Handle, runtime: Handle,
@ -148,7 +148,7 @@ impl PostgresDatabase {
runtime: Handle, runtime: Handle,
postgres_path: String, postgres_path: String,
num_connections: usize, num_connections: usize,
local_identity: Verified<Identity>, local_identity: Valid<Identity>,
) -> Result<Arc<Self>, Error> { ) -> Result<Arc<Self>, Error> {
assert!(num_connections > 0); assert!(num_connections > 0);
let (sender, _) = channel(4096); let (sender, _) = channel(4096);
@ -189,11 +189,11 @@ impl PostgresDatabase {
} }
impl VL1DataStorage for PostgresDatabase { impl VL1DataStorage for PostgresDatabase {
fn load_node_identity(&self) -> Option<Verified<Identity>> { fn load_node_identity(&self) -> Option<Valid<Identity>> {
Some(self.local_identity.clone()) Some(self.local_identity.clone())
} }
fn save_node_identity(&self, id: &Verified<Identity>) -> bool { fn save_node_identity(&self, id: &Valid<Identity>) -> bool {
panic!("local identity saving not supported by PostgresDatabase") panic!("local identity saving not supported by PostgresDatabase")
} }
} }

View file

@ -8,7 +8,7 @@ pub mod poly1305;
pub mod random; pub mod random;
pub mod salsa; pub mod salsa;
pub mod secret; pub mod secret;
pub mod verified; pub mod typestate;
pub mod x25519; pub mod x25519;
pub const ZEROES: [u8; 64] = [0_u8; 64]; pub const ZEROES: [u8; 64] = [0_u8; 64];

View file

@ -4,31 +4,25 @@ use std::fmt::Debug;
use std::hash::Hash; use std::hash::Hash;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
/// A zero-overhead typestate indicating that a credential has been verified as valid. /// Typestate indicating that a credential or other object has been internally validated.
///
/// What this means is obviously specific to the credential.
///
/// The purpose of this is to make code more self-documenting and make it harder to accidentally
/// use an unverified/unvalidated credential (or other security critical object) where a verified
/// one is required.
#[repr(transparent)] #[repr(transparent)]
pub struct Verified<T>(T); pub struct Valid<T>(T);
impl<T> AsRef<T> for Verified<T> { impl<T> AsRef<T> for Valid<T> {
#[inline(always)] #[inline(always)]
fn as_ref(&self) -> &T { fn as_ref(&self) -> &T {
&self.0 &self.0
} }
} }
impl<T> AsMut<T> for Verified<T> { impl<T> AsMut<T> for Valid<T> {
#[inline(always)] #[inline(always)]
fn as_mut(&mut self) -> &mut T { fn as_mut(&mut self) -> &mut T {
&mut self.0 &mut self.0
} }
} }
impl<T> Deref for Verified<T> { impl<T> Deref for Valid<T> {
type Target = T; type Target = T;
#[inline(always)] #[inline(always)]
@ -37,14 +31,14 @@ impl<T> Deref for Verified<T> {
} }
} }
impl<T> DerefMut for Verified<T> { impl<T> DerefMut for Valid<T> {
#[inline(always)] #[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0 &mut self.0
} }
} }
impl<T> Clone for Verified<T> impl<T> Clone for Valid<T>
where where
T: Clone, T: Clone,
{ {
@ -54,7 +48,7 @@ where
} }
} }
impl<T> PartialEq for Verified<T> impl<T> PartialEq for Valid<T>
where where
T: PartialEq, T: PartialEq,
{ {
@ -64,9 +58,9 @@ where
} }
} }
impl<T> Eq for Verified<T> where T: Eq {} impl<T> Eq for Valid<T> where T: Eq {}
impl<T> Ord for Verified<T> impl<T> Ord for Valid<T>
where where
T: Ord, T: Ord,
{ {
@ -76,7 +70,7 @@ where
} }
} }
impl<T> PartialOrd for Verified<T> impl<T> PartialOrd for Valid<T>
where where
T: PartialOrd, T: PartialOrd,
{ {
@ -86,7 +80,7 @@ where
} }
} }
impl<T> Hash for Verified<T> impl<T> Hash for Valid<T>
where where
T: Hash, T: Hash,
{ {
@ -96,7 +90,7 @@ where
} }
} }
impl<T> Debug for Verified<T> impl<T> Debug for Valid<T>
where where
T: Debug, T: Debug,
{ {
@ -106,7 +100,7 @@ where
} }
} }
impl<T> Verified<T> { impl<T> Valid<T> {
/// Strip the Verified typestate off this object. /// Strip the Verified typestate off this object.
#[inline(always)] #[inline(always)]
pub fn unwrap(self) -> T { pub fn unwrap(self) -> T {

View file

@ -9,11 +9,11 @@ use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use zerotier_crypto::{hash::*, secure_eq};
use zerotier_crypto::p384::*; use zerotier_crypto::p384::*;
use zerotier_crypto::salsa::Salsa; use zerotier_crypto::salsa::Salsa;
use zerotier_crypto::secret::Secret; use zerotier_crypto::secret::Secret;
use zerotier_crypto::x25519::*; use zerotier_crypto::x25519::*;
use zerotier_crypto::{hash::*, secure_eq};
use zerotier_utils::arrayvec::ArrayVec; use zerotier_utils::arrayvec::ArrayVec;
use zerotier_utils::buffer::Buffer; use zerotier_utils::buffer::Buffer;
@ -23,7 +23,7 @@ use zerotier_utils::{base64_decode_url_nopad, base64_encode_url_nopad, hex};
use crate::protocol::{ADDRESS_SIZE, ADDRESS_SIZE_STRING, IDENTITY_POW_THRESHOLD}; use crate::protocol::{ADDRESS_SIZE, ADDRESS_SIZE_STRING, IDENTITY_POW_THRESHOLD};
use crate::vl1::Address; use crate::vl1::Address;
use crate::vl1::Verified; use crate::vl1::Valid;
/// Current maximum size for an identity signature. /// Current maximum size for an identity signature.
pub const IDENTITY_MAX_SIGNATURE_SIZE: usize = P384_ECDSA_SIGNATURE_SIZE + 1; pub const IDENTITY_MAX_SIGNATURE_SIZE: usize = P384_ECDSA_SIGNATURE_SIZE + 1;
@ -166,7 +166,7 @@ impl Identity {
const FLAG_INCLUDES_SECRETS: u8 = 0x80; const FLAG_INCLUDES_SECRETS: u8 = 0x80;
/// Generate a new identity. /// Generate a new identity.
pub fn generate() -> Verified<Self> { pub fn generate() -> Valid<Self> {
// First generate an identity with just x25519 keys and derive its address. // First generate an identity with just x25519 keys and derive its address.
let mut sha = SHA512::new(); let mut sha = SHA512::new();
let ed25519 = Ed25519KeyPair::generate(); let ed25519 = Ed25519KeyPair::generate();
@ -206,7 +206,7 @@ impl Identity {
assert!(id.upgrade().is_ok()); assert!(id.upgrade().is_ok());
assert!(id.p384.is_some() && id.secret.as_ref().unwrap().p384.is_some()); assert!(id.p384.is_some() && id.secret.as_ref().unwrap().p384.is_some());
Verified::assume_verified(id) Valid::assume_verified(id)
} }
/// Upgrade older x25519-only identities to hybrid identities with both x25519 and NIST P-384 curves. /// Upgrade older x25519-only identities to hybrid identities with both x25519 and NIST P-384 curves.
@ -290,7 +290,7 @@ impl Identity {
/// Locally check the validity of this identity. /// Locally check the validity of this identity.
/// ///
/// This is somewhat time consuming due to the memory-intensive work algorithm. /// This is somewhat time consuming due to the memory-intensive work algorithm.
pub fn validate(self) -> Option<Verified<Self>> { pub fn validate(self) -> Option<Valid<Self>> {
if let Some(p384) = self.p384.as_ref() { if let Some(p384) = self.p384.as_ref() {
let mut self_sign_buf: Vec<u8> = Vec::with_capacity( let mut self_sign_buf: Vec<u8> = Vec::with_capacity(
ADDRESS_SIZE + 4 + C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE, ADDRESS_SIZE + 4 + C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE,
@ -321,7 +321,7 @@ impl Identity {
zt_address_derivation_work_function(&mut digest); zt_address_derivation_work_function(&mut digest);
return if digest[0] < IDENTITY_POW_THRESHOLD && Address::from_bytes(&digest[59..64]).map_or(false, |a| a == self.address) { return if digest[0] < IDENTITY_POW_THRESHOLD && Address::from_bytes(&digest[59..64]).map_or(false, |a| a == self.address) {
Some(Verified::assume_verified(self)) Some(Valid::assume_verified(self))
} else { } else {
None None
}; };
@ -345,7 +345,7 @@ impl Identity {
/// For new identities with P-384 keys a hybrid agreement is performed using both X25519 and NIST P-384 ECDH. /// For new identities with P-384 keys a hybrid agreement is performed using both X25519 and NIST P-384 ECDH.
/// The final key is derived as HMAC(x25519 secret, p-384 secret) to yield a FIPS-compliant key agreement with /// The final key is derived as HMAC(x25519 secret, p-384 secret) to yield a FIPS-compliant key agreement with
/// the X25519 secret being used as a "salt" as far as FIPS is concerned. /// the X25519 secret being used as a "salt" as far as FIPS is concerned.
pub fn agree(&self, other: &Verified<Identity>) -> Option<Secret<64>> { pub fn agree(&self, other: &Valid<Identity>) -> Option<Secret<64>> {
if let Some(secret) = self.secret.as_ref() { if let Some(secret) = self.secret.as_ref() {
let c25519_secret: Secret<64> = Secret(SHA512::hash(&secret.x25519.agree(&other.x25519).0)); let c25519_secret: Secret<64> = Secret(SHA512::hash(&secret.x25519.agree(&other.x25519).0));

View file

@ -23,7 +23,7 @@ pub use path::Path;
pub use peer::Peer; pub use peer::Peer;
pub use rootset::{Root, RootSet}; pub use rootset::{Root, RootSet};
pub use zerotier_crypto::verified::Verified; pub use zerotier_crypto::typestate::Valid;
#[cfg(feature = "debug_events")] #[cfg(feature = "debug_events")]
#[allow(unused_macros)] #[allow(unused_macros)]

View file

@ -17,7 +17,7 @@ use crate::vl1::identity::Identity;
use crate::vl1::path::{Path, PathServiceResult}; use crate::vl1::path::{Path, PathServiceResult};
use crate::vl1::peer::Peer; use crate::vl1::peer::Peer;
use crate::vl1::rootset::RootSet; use crate::vl1::rootset::RootSet;
use crate::vl1::Verified; use crate::vl1::Valid;
use zerotier_crypto::random; use zerotier_crypto::random;
use zerotier_utils::error::InvalidParameterError; use zerotier_utils::error::InvalidParameterError;
@ -42,10 +42,10 @@ pub trait ApplicationLayer: Sync + Send {
fn event(&self, event: Event); fn event(&self, event: Event);
/// Load this node's identity from the data store. /// Load this node's identity from the data store.
fn load_node_identity(&self) -> Option<Verified<Identity>>; fn load_node_identity(&self) -> Option<Valid<Identity>>;
/// Save this node's identity to the data store, returning true on success. /// Save this node's identity to the data store, returning true on success.
fn save_node_identity(&self, id: &Verified<Identity>) -> bool; fn save_node_identity(&self, id: &Valid<Identity>) -> bool;
/// Get a pooled packet buffer for internal use. /// Get a pooled packet buffer for internal use.
fn get_buffer(&self) -> PooledPacketBuffer; fn get_buffer(&self) -> PooledPacketBuffer;
@ -84,7 +84,7 @@ pub trait ApplicationLayer: Sync + Send {
#[allow(unused_variables)] #[allow(unused_variables)]
fn should_use_physical_path<Application: ApplicationLayer + ?Sized>( fn should_use_physical_path<Application: ApplicationLayer + ?Sized>(
&self, &self,
id: &Verified<Identity>, id: &Valid<Identity>,
endpoint: &Endpoint, endpoint: &Endpoint,
local_socket: Option<&Application::LocalSocket>, local_socket: Option<&Application::LocalSocket>,
local_interface: Option<&Application::LocalInterface>, local_interface: Option<&Application::LocalInterface>,
@ -98,7 +98,7 @@ pub trait ApplicationLayer: Sync + Send {
#[allow(unused_variables)] #[allow(unused_variables)]
fn get_path_hints<Application: ApplicationLayer + ?Sized>( fn get_path_hints<Application: ApplicationLayer + ?Sized>(
&self, &self,
id: &Verified<Identity>, id: &Valid<Identity>,
) -> Option<Vec<(Endpoint, Option<Application::LocalSocket>, Option<Application::LocalInterface>)>> { ) -> Option<Vec<(Endpoint, Option<Application::LocalSocket>, Option<Application::LocalInterface>)>> {
None None
} }
@ -133,7 +133,7 @@ pub trait InnerProtocolLayer: Sync + Send {
/// Check if this node should respond to messages from a given peer at all. /// Check if this node should respond to messages from a given peer at all.
/// ///
/// The default implementation always returns true. /// The default implementation always returns true.
fn should_respond_to(&self, id: &Verified<Identity>) -> bool { fn should_respond_to(&self, id: &Valid<Identity>) -> bool {
true true
} }
@ -144,7 +144,7 @@ pub trait InnerProtocolLayer: Sync + Send {
/// some privileged relationship like mutual membership in a network. /// some privileged relationship like mutual membership in a network.
/// ///
/// The default implementation always returns true. /// The default implementation always returns true.
fn has_trust_relationship(&self, id: &Verified<Identity>) -> bool { fn has_trust_relationship(&self, id: &Valid<Identity>) -> bool {
true true
} }
@ -207,7 +207,7 @@ pub trait InnerProtocolLayer: Sync + Send {
struct RootInfo { struct RootInfo {
/// Root sets to which we are a member. /// Root sets to which we are a member.
sets: HashMap<String, Verified<RootSet>>, sets: HashMap<String, Valid<RootSet>>,
/// Root peers and their statically defined endpoints (from root sets). /// Root peers and their statically defined endpoints (from root sets).
roots: HashMap<Arc<Peer>, Vec<Endpoint>>, roots: HashMap<Arc<Peer>, Vec<Endpoint>>,
@ -251,7 +251,7 @@ pub struct Node {
pub instance_id: [u8; 16], pub instance_id: [u8; 16],
/// This node's identity and permanent keys. /// This node's identity and permanent keys.
pub identity: Verified<Identity>, pub identity: Valid<Identity>,
/// Interval latches for periodic background tasks. /// Interval latches for periodic background tasks.
intervals: Mutex<BackgroundTaskIntervals>, intervals: Mutex<BackgroundTaskIntervals>,
@ -352,7 +352,7 @@ impl Node {
/// Add a new root set or update the existing root set if the new root set is newer and otherwise matches. /// Add a new root set or update the existing root set if the new root set is newer and otherwise matches.
#[inline] #[inline]
pub fn add_update_root_set(&self, rs: Verified<RootSet>) -> bool { pub fn add_update_root_set(&self, rs: Valid<RootSet>) -> bool {
let mut roots = self.roots.write().unwrap(); let mut roots = self.roots.write().unwrap();
if let Some(entry) = roots.sets.get_mut(&rs.name) { if let Some(entry) = roots.sets.get_mut(&rs.name) {
if rs.should_replace(entry) { if rs.should_replace(entry) {
@ -468,8 +468,7 @@ impl Node {
if let Some(peer) = peers.get(&m.identity.address) { if let Some(peer) = peers.get(&m.identity.address) {
new_roots.insert(peer.clone(), m.endpoints.as_ref().unwrap().iter().cloned().collect()); new_roots.insert(peer.clone(), m.endpoints.as_ref().unwrap().iter().cloned().collect());
} else { } else {
if let Some(peer) = Peer::new(&self.identity, Verified::assume_verified(m.identity.clone()), time_ticks) if let Some(peer) = Peer::new(&self.identity, Valid::assume_verified(m.identity.clone()), time_ticks) {
{
drop(peers); drop(peers);
new_roots.insert( new_roots.insert(
self.peers self.peers
@ -968,7 +967,7 @@ impl Node {
/// This will only replace an existing root set with a newer one. It won't add a new root set, which must be /// This will only replace an existing root set with a newer one. It won't add a new root set, which must be
/// done by an authorized user or administrator not just by a root. /// done by an authorized user or administrator not just by a root.
#[allow(unused)] #[allow(unused)]
pub(crate) fn on_remote_update_root_set(&self, received_from: &Identity, rs: Verified<RootSet>) { pub(crate) fn on_remote_update_root_set(&self, received_from: &Identity, rs: Valid<RootSet>) {
let mut roots = self.roots.write().unwrap(); let mut roots = self.roots.write().unwrap();
if let Some(entry) = roots.sets.get_mut(&rs.name) { if let Some(entry) = roots.sets.get_mut(&rs.name) {
if entry.members.iter().any(|m| m.identity.eq(received_from)) && rs.should_replace(entry) { if entry.members.iter().any(|m| m.identity.eq(received_from)) && rs.should_replace(entry) {

View file

@ -18,14 +18,14 @@ use crate::protocol::*;
use crate::vl1::address::Address; use crate::vl1::address::Address;
use crate::vl1::debug_event; use crate::vl1::debug_event;
use crate::vl1::node::*; use crate::vl1::node::*;
use crate::vl1::Verified; use crate::vl1::Valid;
use crate::vl1::{Endpoint, Identity, Path}; use crate::vl1::{Endpoint, Identity, Path};
use crate::{VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION}; use crate::{VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION};
pub(crate) const SERVICE_INTERVAL_MS: i64 = 10000; pub(crate) const SERVICE_INTERVAL_MS: i64 = 10000;
pub struct Peer { pub struct Peer {
pub identity: Verified<Identity>, pub identity: Valid<Identity>,
v1_proto_static_secret: v1::SymmetricSecret, v1_proto_static_secret: v1::SymmetricSecret,
paths: Mutex<Vec<PeerPath>>, paths: Mutex<Vec<PeerPath>>,
@ -62,7 +62,7 @@ impl Peer {
/// ///
/// This only returns None if this_node_identity does not have its secrets or if some /// This only returns None if this_node_identity does not have its secrets or if some
/// fatal error occurs performing key agreement between the two identities. /// fatal error occurs performing key agreement between the two identities.
pub(crate) fn new(this_node_identity: &Verified<Identity>, id: Verified<Identity>, time_ticks: i64) -> Option<Self> { pub(crate) fn new(this_node_identity: &Valid<Identity>, id: Valid<Identity>, time_ticks: i64) -> Option<Self> {
this_node_identity.agree(&id).map(|static_secret| -> Self { this_node_identity.agree(&id).map(|static_secret| -> Self {
Self { Self {
identity: id, identity: id,

View file

@ -6,7 +6,7 @@ use std::io::Write;
use crate::vl1::identity::{Identity, IDENTITY_MAX_SIGNATURE_SIZE}; use crate::vl1::identity::{Identity, IDENTITY_MAX_SIGNATURE_SIZE};
use crate::vl1::Endpoint; use crate::vl1::Endpoint;
use zerotier_crypto::verified::Verified; use zerotier_crypto::typestate::Valid;
use zerotier_utils::arrayvec::ArrayVec; use zerotier_utils::arrayvec::ArrayVec;
use zerotier_utils::buffer::Buffer; use zerotier_utils::buffer::Buffer;
use zerotier_utils::marshalable::{Marshalable, UnmarshalError}; use zerotier_utils::marshalable::{Marshalable, UnmarshalError};
@ -91,7 +91,7 @@ impl RootSet {
} }
/// Get the ZeroTier default root set, which contains roots run by ZeroTier Inc. /// Get the ZeroTier default root set, which contains roots run by ZeroTier Inc.
pub fn zerotier_default() -> Verified<Self> { pub fn zerotier_default() -> Valid<Self> {
let mut cursor = 0; let mut cursor = 0;
let rs = include_bytes!("../../default-rootset/root.zerotier.com.bin"); let rs = include_bytes!("../../default-rootset/root.zerotier.com.bin");
//let rs = include_bytes!("../../default-rootset/test-root.bin"); //let rs = include_bytes!("../../default-rootset/test-root.bin");
@ -107,7 +107,7 @@ impl RootSet {
} }
/// Verify signatures present in this root cluster definition. /// Verify signatures present in this root cluster definition.
pub fn verify(self) -> Option<Verified<Self>> { pub fn verify(self) -> Option<Valid<Self>> {
if self.members.is_empty() { if self.members.is_empty() {
return None; return None;
} }
@ -119,7 +119,7 @@ impl RootSet {
} }
} }
return Some(Verified::assume_verified(self)); return Some(Valid::assume_verified(self));
} }
/// Add a member to this definition, replacing any current entry with this address. /// Add a member to this definition, replacing any current entry with this address.

View file

@ -1,6 +1,6 @@
use std::io::Write; use std::io::Write;
use zerotier_crypto::verified::Verified; use zerotier_crypto::typestate::Valid;
use zerotier_utils::arrayvec::ArrayVec; use zerotier_utils::arrayvec::ArrayVec;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -26,7 +26,7 @@ impl Revocation {
threshold: i64, threshold: i64,
target: Address, target: Address,
issued_to: Address, issued_to: Address,
signer: &Verified<Identity>, signer: &Valid<Identity>,
fast_propagate: bool, fast_propagate: bool,
) -> Option<Self> { ) -> Option<Self> {
let mut r = Self { let mut r = Self {

View file

@ -11,11 +11,11 @@ pub struct Switch {}
#[allow(unused_variables)] #[allow(unused_variables)]
impl InnerProtocolLayer for Switch { impl InnerProtocolLayer for Switch {
fn should_respond_to(&self, id: &zerotier_crypto::verified::Verified<crate::vl1::Identity>) -> bool { fn should_respond_to(&self, id: &zerotier_crypto::typestate::Valid<crate::vl1::Identity>) -> bool {
true true
} }
fn has_trust_relationship(&self, id: &zerotier_crypto::verified::Verified<crate::vl1::Identity>) -> bool { fn has_trust_relationship(&self, id: &zerotier_crypto::typestate::Valid<crate::vl1::Identity>) -> bool {
true true
} }

View file

@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
use zerotier_crypto::hash::SHA384; use zerotier_crypto::hash::SHA384;
use zerotier_crypto::secure_eq; use zerotier_crypto::secure_eq;
use zerotier_crypto::verified::Verified; use zerotier_crypto::typestate::Valid;
use zerotier_utils::arrayvec::ArrayVec; use zerotier_utils::arrayvec::ArrayVec;
use zerotier_utils::blob::Blob; use zerotier_utils::blob::Blob;
use zerotier_utils::error::InvalidParameterError; use zerotier_utils::error::InvalidParameterError;
@ -171,10 +171,13 @@ impl CertificateOfMembership {
} }
/// Verify this certificate of membership. /// Verify this certificate of membership.
pub fn verify(self, issuer: &Identity, expect_issued_to: &Identity) -> Option<Verified<Self>> { pub fn verify(self, issuer: &Identity, expect_issued_to: &Identity) -> Option<Valid<Self>> {
if secure_eq(&Self::v1_proto_issued_to_fingerprint(expect_issued_to), &self.issued_to_fingerprint.as_bytes()[..32]) { if secure_eq(
&Self::v1_proto_issued_to_fingerprint(expect_issued_to),
&self.issued_to_fingerprint.as_bytes()[..32],
) {
if issuer.verify(&self.v1_proto_get_qualifier_bytes(), self.signature.as_bytes()) { if issuer.verify(&self.v1_proto_get_qualifier_bytes(), self.signature.as_bytes()) {
return Some(Verified::assume_verified(self)); return Some(Valid::assume_verified(self));
} }
} }
return None; return None;

View file

@ -8,7 +8,7 @@ use serde::de::DeserializeOwned;
use serde::Serialize; use serde::Serialize;
use zerotier_crypto::random::next_u32_secure; use zerotier_crypto::random::next_u32_secure;
use zerotier_network_hypervisor::vl1::{Identity, Verified}; use zerotier_network_hypervisor::vl1::{Identity, Valid};
use zerotier_utils::io::{fs_restrict_permissions, read_limit, DEFAULT_FILE_IO_READ_LIMIT}; use zerotier_utils::io::{fs_restrict_permissions, read_limit, DEFAULT_FILE_IO_READ_LIMIT};
use zerotier_utils::json::to_json_pretty; use zerotier_utils::json::to_json_pretty;
@ -22,7 +22,7 @@ pub const CONFIG_FILENAME: &'static str = "local.conf";
const AUTH_TOKEN_DEFAULT_LENGTH: usize = 48; const AUTH_TOKEN_DEFAULT_LENGTH: usize = 48;
const AUTH_TOKEN_POSSIBLE_CHARS: &'static str = "0123456789abcdefghijklmnopqrstuvwxyz"; const AUTH_TOKEN_POSSIBLE_CHARS: &'static str = "0123456789abcdefghijklmnopqrstuvwxyz";
pub fn load_node_identity(base_path: &Path) -> Option<Verified<Identity>> { pub fn load_node_identity(base_path: &Path) -> Option<Valid<Identity>> {
let id_data = read_limit(base_path.join(IDENTITY_SECRET_FILENAME), 4096); let id_data = read_limit(base_path.join(IDENTITY_SECRET_FILENAME), 4096);
if id_data.is_err() { if id_data.is_err() {
return None; return None;
@ -31,10 +31,10 @@ pub fn load_node_identity(base_path: &Path) -> Option<Verified<Identity>> {
if id_data.is_err() { if id_data.is_err() {
return None; return None;
} }
Some(Verified::assume_verified(id_data.unwrap())) Some(Valid::assume_verified(id_data.unwrap()))
} }
pub fn save_node_identity(base_path: &Path, id: &Verified<Identity>) -> bool { pub fn save_node_identity(base_path: &Path, id: &Valid<Identity>) -> bool {
assert!(id.secret.is_some()); assert!(id.secret.is_some());
let id_secret_str = id.to_secret_string(); let id_secret_str = id.to_secret_string();
let id_public_str = id.to_string(); let id_public_str = id.to_string();
@ -53,11 +53,11 @@ pub struct DataDir<Config: PartialEq + Eq + Clone + Send + Sync + Default + Seri
} }
impl<Config: PartialEq + Eq + Clone + Send + Sync + Default + Serialize + DeserializeOwned + 'static> VL1DataStorage for DataDir<Config> { impl<Config: PartialEq + Eq + Clone + Send + Sync + Default + Serialize + DeserializeOwned + 'static> VL1DataStorage for DataDir<Config> {
fn load_node_identity(&self) -> Option<Verified<Identity>> { fn load_node_identity(&self) -> Option<Valid<Identity>> {
load_node_identity(self.base_path.as_path()) load_node_identity(self.base_path.as_path())
} }
fn save_node_identity(&self, id: &Verified<Identity>) -> bool { fn save_node_identity(&self, id: &Valid<Identity>) -> bool {
save_node_identity(self.base_path.as_path(), id) save_node_identity(self.base_path.as_path(), id)
} }
} }

View file

@ -22,8 +22,8 @@ const UPDATE_UDP_BINDINGS_EVERY_SECS: usize = 10;
/// Trait to implement to provide storage for VL1-related state information. /// Trait to implement to provide storage for VL1-related state information.
pub trait VL1DataStorage: Sync + Send { pub trait VL1DataStorage: Sync + Send {
fn load_node_identity(&self) -> Option<Verified<Identity>>; fn load_node_identity(&self) -> Option<Valid<Identity>>;
fn save_node_identity(&self, id: &Verified<Identity>) -> bool; fn save_node_identity(&self, id: &Valid<Identity>) -> bool;
} }
/// VL1 service that connects to the physical network and hosts an inner protocol like ZeroTier VL2. /// VL1 service that connects to the physical network and hosts an inner protocol like ZeroTier VL2.
@ -218,12 +218,12 @@ impl<Inner: InnerProtocolLayer + ?Sized + 'static> ApplicationLayer for VL1Servi
} }
#[inline] #[inline]
fn load_node_identity(&self) -> Option<Verified<Identity>> { fn load_node_identity(&self) -> Option<Valid<Identity>> {
self.vl1_data_storage.load_node_identity() self.vl1_data_storage.load_node_identity()
} }
#[inline] #[inline]
fn save_node_identity(&self, id: &Verified<Identity>) -> bool { fn save_node_identity(&self, id: &Valid<Identity>) -> bool {
self.vl1_data_storage.save_node_identity(id) self.vl1_data_storage.save_node_identity(id)
} }