2023-02-27 02:58:45 +00:00
#![ allow(clippy::unwrap_used) ]
#![ allow(clippy::expect_used) ]
use crate ::netmask ;
use std ::net ::Ipv4Addr ;
2023-02-27 18:45:02 +00:00
use std ::ops ::{ Add , Sub } ;
2023-02-27 15:04:10 +00:00
use std ::time ::{ Duration , SystemTime , SystemTimeError , UNIX_EPOCH } ;
2023-02-27 02:58:45 +00:00
use ipnet ::Ipv4Net ;
2023-03-29 15:18:33 +00:00
use crate ::cert ::{ CertificateValidity , deserialize_ed25519_private , deserialize_ed25519_public , deserialize_ed25519_public_many , deserialize_nebula_certificate , deserialize_nebula_certificate_from_pem , deserialize_x25519_private , deserialize_x25519_public , NebulaCertificate , NebulaCertificateDetails , serialize_ed25519_private , serialize_ed25519_public , serialize_x25519_private , serialize_x25519_public } ;
2023-02-27 02:58:45 +00:00
use std ::str ::FromStr ;
2023-02-27 18:45:02 +00:00
use ed25519_dalek ::{ SigningKey , VerifyingKey } ;
use quick_protobuf ::{ MessageWrite , Writer } ;
2023-02-27 15:55:53 +00:00
use rand ::rngs ::OsRng ;
2023-02-27 19:42:49 +00:00
use crate ::ca ::{ NebulaCAPool } ;
2023-02-27 18:45:02 +00:00
use crate ::cert_codec ::{ RawNebulaCertificate , RawNebulaCertificateDetails } ;
2023-02-27 02:58:45 +00:00
2023-02-27 15:04:10 +00:00
/// This is a cert that we (e3team) actually use in production, and it's a known-good certificate.
pub const KNOWN_GOOD_CERT : & [ u8 ; 258 ] = b " -----BEGIN NEBULA CERTIFICATE----- \n CkkKF2UzdGVhbSBJbnRlcm5hbCBOZXR3b3JrKJWev5wGMJWFxKsGOiCvpwoHyKY5 \n 8Q5+2XxDjtoCf/zlNY/EUdB8bwXQSwEo50ABEkB0Dx76lkMqc3IyH5+ml2dKjTyv \n B4Jiw6x3abf5YZcf8rDuVEgQpvFdJmo3xJyIb3C9vKZ6kXsUxjw6s1JdWgkA \n -----END NEBULA CERTIFICATE----- " ;
2023-02-27 02:58:45 +00:00
#[ test ]
fn certificate_serialization ( ) {
2023-02-27 15:04:10 +00:00
let before = round_systime_to_secs ( SystemTime ::now ( ) - Duration ::from_secs ( 60 ) ) . unwrap ( ) ;
let after = round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 ) ) . unwrap ( ) ;
2023-02-27 02:58:45 +00:00
let pub_key = b " 1234567890abcedfghij1234567890ab " ;
let cert = NebulaCertificate {
details : NebulaCertificateDetails {
name : " testing " . to_string ( ) ,
ips : vec ! [
netmask! ( " 10.1.1.1 " , " 255.255.255.0 " ) ,
netmask! ( " 10.1.1.2 " , " 255.255.0.0 " ) ,
2023-02-27 15:04:10 +00:00
netmask! ( " 10.1.1.3 " , " 255.0.0.0 " )
2023-02-27 02:58:45 +00:00
] ,
subnets : vec ! [
2023-02-27 15:04:10 +00:00
netmask! ( " 9.1.1.1 " , " 255.255.255.128 " ) ,
2023-02-27 02:58:45 +00:00
netmask! ( " 9.1.1.2 " , " 255.255.255.0 " ) ,
netmask! ( " 9.1.1.3 " , " 255.255.0.0 " )
] ,
groups : vec ! [ " test-group1 " . to_string ( ) , " test-group2 " . to_string ( ) , " test-group3 " . to_string ( ) ] ,
not_before : before ,
not_after : after ,
public_key : * pub_key ,
is_ca : false ,
2023-02-27 15:04:10 +00:00
issuer : " 1234567890abcedfabcd1234567890ab " . to_string ( ) ,
2023-02-27 02:58:45 +00:00
} ,
2023-02-27 02:59:46 +00:00
signature : b " 1234567890abcedfghij1234567890ab " . to_vec ( ) ,
2023-02-27 02:58:45 +00:00
} ;
let bytes = cert . serialize ( ) . unwrap ( ) ;
let deserialized = deserialize_nebula_certificate ( & bytes ) . unwrap ( ) ;
2023-02-27 15:24:30 +00:00
2023-02-27 02:58:45 +00:00
assert_eq! ( cert . signature , deserialized . signature ) ;
assert_eq! ( cert . details . name , deserialized . details . name ) ;
2023-02-27 15:04:10 +00:00
assert_eq! ( cert . details . not_before , deserialized . details . not_before ) ;
assert_eq! ( cert . details . not_after , deserialized . details . not_after ) ;
assert_eq! ( cert . details . public_key , deserialized . details . public_key ) ;
2023-02-27 15:24:30 +00:00
assert_eq! ( cert . details . is_ca , deserialized . details . is_ca ) ;
assert_eq! ( cert . details . ips . len ( ) , deserialized . details . ips . len ( ) ) ;
for item in & cert . details . ips {
assert! ( deserialized . details . ips . contains ( item ) , " deserialized does not contain from source " ) ;
}
assert_eq! ( cert . details . subnets . len ( ) , deserialized . details . subnets . len ( ) ) ;
for item in & cert . details . subnets {
assert! ( deserialized . details . subnets . contains ( item ) , " deserialized does not contain from source " ) ;
}
assert_eq! ( cert . details . groups . len ( ) , deserialized . details . groups . len ( ) ) ;
for item in & cert . details . groups {
assert! ( deserialized . details . groups . contains ( item ) , " deserialized does not contain from source " ) ;
}
2023-02-27 02:58:45 +00:00
}
2023-02-27 18:45:02 +00:00
#[ test ]
fn certificate_serialization_pem ( ) {
let before = round_systime_to_secs ( SystemTime ::now ( ) - Duration ::from_secs ( 60 ) ) . unwrap ( ) ;
let after = round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 ) ) . unwrap ( ) ;
let pub_key = b " 1234567890abcedfghij1234567890ab " ;
let cert = NebulaCertificate {
details : NebulaCertificateDetails {
name : " testing " . to_string ( ) ,
ips : vec ! [
netmask! ( " 10.1.1.1 " , " 255.255.255.0 " ) ,
netmask! ( " 10.1.1.2 " , " 255.255.0.0 " ) ,
netmask! ( " 10.1.1.3 " , " 255.0.0.0 " )
] ,
subnets : vec ! [
netmask! ( " 9.1.1.1 " , " 255.255.255.128 " ) ,
netmask! ( " 9.1.1.2 " , " 255.255.255.0 " ) ,
netmask! ( " 9.1.1.3 " , " 255.255.0.0 " )
] ,
groups : vec ! [ " test-group1 " . to_string ( ) , " test-group2 " . to_string ( ) , " test-group3 " . to_string ( ) ] ,
not_before : before ,
not_after : after ,
public_key : * pub_key ,
is_ca : false ,
issuer : " 1234567890abcedfabcd1234567890ab " . to_string ( ) ,
} ,
signature : b " 1234567890abcedfghij1234567890ab " . to_vec ( ) ,
} ;
let bytes = cert . serialize_to_pem ( ) . unwrap ( ) ;
let deserialized = deserialize_nebula_certificate_from_pem ( & bytes ) . unwrap ( ) ;
assert_eq! ( cert . signature , deserialized . signature ) ;
assert_eq! ( cert . details . name , deserialized . details . name ) ;
assert_eq! ( cert . details . not_before , deserialized . details . not_before ) ;
assert_eq! ( cert . details . not_after , deserialized . details . not_after ) ;
assert_eq! ( cert . details . public_key , deserialized . details . public_key ) ;
assert_eq! ( cert . details . is_ca , deserialized . details . is_ca ) ;
assert_eq! ( cert . details . ips . len ( ) , deserialized . details . ips . len ( ) ) ;
for item in & cert . details . ips {
assert! ( deserialized . details . ips . contains ( item ) , " deserialized does not contain from source " ) ;
}
assert_eq! ( cert . details . subnets . len ( ) , deserialized . details . subnets . len ( ) ) ;
for item in & cert . details . subnets {
assert! ( deserialized . details . subnets . contains ( item ) , " deserialized does not contain from source " ) ;
}
assert_eq! ( cert . details . groups . len ( ) , deserialized . details . groups . len ( ) ) ;
for item in & cert . details . groups {
assert! ( deserialized . details . groups . contains ( item ) , " deserialized does not contain from source " ) ;
}
}
2023-02-27 15:55:53 +00:00
#[ test ]
fn cert_signing ( ) {
let before = round_systime_to_secs ( SystemTime ::now ( ) - Duration ::from_secs ( 60 ) ) . unwrap ( ) ;
let after = round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 ) ) . unwrap ( ) ;
let pub_key = b " 1234567890abcedfghij1234567890ab " ;
let mut cert = NebulaCertificate {
details : NebulaCertificateDetails {
name : " testing " . to_string ( ) ,
ips : vec ! [
netmask! ( " 10.1.1.1 " , " 255.255.255.0 " ) ,
netmask! ( " 10.1.1.2 " , " 255.255.0.0 " ) ,
netmask! ( " 10.1.1.3 " , " 255.0.0.0 " )
] ,
subnets : vec ! [
netmask! ( " 9.1.1.1 " , " 255.255.255.128 " ) ,
netmask! ( " 9.1.1.2 " , " 255.255.255.0 " ) ,
netmask! ( " 9.1.1.3 " , " 255.255.0.0 " )
] ,
groups : vec ! [ " test-group1 " . to_string ( ) , " test-group2 " . to_string ( ) , " test-group3 " . to_string ( ) ] ,
not_before : before ,
not_after : after ,
public_key : * pub_key ,
is_ca : false ,
issuer : " 1234567890abcedfabcd1234567890ab " . to_string ( ) ,
} ,
signature : b " 1234567890abcedfghij1234567890ab " . to_vec ( ) ,
} ;
let mut csprng = OsRng ;
let key = SigningKey ::generate ( & mut csprng ) ;
assert! ( cert . check_signature ( & key . verifying_key ( ) ) . is_err ( ) ) ;
cert . sign ( & key ) . unwrap ( ) ;
assert! ( cert . check_signature ( & key . verifying_key ( ) ) . unwrap ( ) ) ;
}
2023-02-27 18:45:02 +00:00
#[ test ]
fn cert_expiry ( ) {
let cert = NebulaCertificate {
details : NebulaCertificateDetails {
name : String ::new ( ) ,
ips : vec ! [ ] ,
subnets : vec ! [ ] ,
groups : vec ! [ ] ,
not_before : SystemTime ::now ( ) . sub ( Duration ::from_secs ( 60 ) ) ,
not_after : SystemTime ::now ( ) . add ( Duration ::from_secs ( 60 ) ) ,
public_key : [ 0 u8 ; 32 ] ,
is_ca : false ,
issuer : String ::new ( ) ,
} ,
signature : vec ! [ ] ,
} ;
assert! ( cert . expired ( SystemTime ::now ( ) . add ( Duration ::from_secs ( 60 * 60 * 60 ) ) ) ) ;
assert! ( cert . expired ( SystemTime ::now ( ) . sub ( Duration ::from_secs ( 60 * 60 * 60 ) ) ) ) ;
assert! ( ! cert . expired ( SystemTime ::now ( ) ) ) ;
}
#[ test ]
fn cert_display ( ) {
let cert = NebulaCertificate {
details : NebulaCertificateDetails {
name : String ::new ( ) ,
ips : vec ! [ ] ,
subnets : vec ! [ ] ,
groups : vec ! [ ] ,
not_before : SystemTime ::now ( ) . sub ( Duration ::from_secs ( 60 ) ) ,
not_after : SystemTime ::now ( ) . add ( Duration ::from_secs ( 60 ) ) ,
public_key : [ 0 u8 ; 32 ] ,
is_ca : false ,
issuer : String ::new ( ) ,
} ,
signature : vec ! [ ] ,
} ;
println! ( " {cert} " ) ;
}
#[ test ]
#[ should_panic ]
fn cert_deserialize_empty_bytes ( ) {
deserialize_nebula_certificate ( & [ ] ) . unwrap ( ) ;
}
#[ test ]
fn cert_deserialize_unpaired_ips ( ) {
let broken_cert = RawNebulaCertificate {
Details : Some ( RawNebulaCertificateDetails {
Name : String ::new ( ) ,
Ips : vec ! [ 0 ] ,
Subnets : vec ! [ ] ,
Groups : vec ! [ ] ,
NotBefore : 0 ,
NotAfter : 0 ,
PublicKey : vec ! [ ] ,
IsCA : false ,
Issuer : vec ! [ ] ,
} ) ,
Signature : vec ! [ ] ,
} ;
let mut bytes = vec! [ ] ;
let mut writer = Writer ::new ( & mut bytes ) ;
broken_cert . write_message ( & mut writer ) . unwrap ( ) ;
deserialize_nebula_certificate ( & bytes ) . unwrap_err ( ) ;
}
#[ test ]
fn cert_deserialize_unpaired_subnets ( ) {
let broken_cert = RawNebulaCertificate {
Details : Some ( RawNebulaCertificateDetails {
Name : String ::new ( ) ,
Ips : vec ! [ ] ,
Subnets : vec ! [ 0 ] ,
Groups : vec ! [ ] ,
NotBefore : 0 ,
NotAfter : 0 ,
PublicKey : vec ! [ ] ,
IsCA : false ,
Issuer : vec ! [ ] ,
} ) ,
Signature : vec ! [ ] ,
} ;
let mut bytes = vec! [ ] ;
let mut writer = Writer ::new ( & mut bytes ) ;
broken_cert . write_message ( & mut writer ) . unwrap ( ) ;
deserialize_nebula_certificate ( & bytes ) . unwrap_err ( ) ;
}
#[ test ]
fn cert_deserialize_wrong_pubkey_len ( ) {
let broken_cert = RawNebulaCertificate {
Details : Some ( RawNebulaCertificateDetails {
Name : String ::new ( ) ,
Ips : vec ! [ ] ,
Subnets : vec ! [ ] ,
Groups : vec ! [ ] ,
NotBefore : 0 ,
NotAfter : 0 ,
PublicKey : vec ! [ 0 u8 ; 31 ] ,
IsCA : false ,
Issuer : vec ! [ ] ,
} ) ,
Signature : vec ! [ ] ,
} ;
let mut bytes = vec! [ ] ;
let mut writer = Writer ::new ( & mut bytes ) ;
broken_cert . write_message ( & mut writer ) . unwrap ( ) ;
deserialize_nebula_certificate ( & bytes ) . unwrap_err ( ) ;
assert! ( deserialize_nebula_certificate_from_pem ( & [ 0 u8 ; 32 ] ) . is_err ( ) ) ;
}
#[ test ]
fn x25519_serialization ( ) {
let bytes = [ 0 u8 ; 32 ] ;
assert_eq! ( deserialize_x25519_private ( & serialize_x25519_private ( & bytes ) ) . unwrap ( ) , bytes ) ;
assert! ( deserialize_x25519_private ( & [ 0 u8 ; 32 ] ) . is_err ( ) ) ;
assert_eq! ( deserialize_x25519_public ( & serialize_x25519_public ( & bytes ) ) . unwrap ( ) , bytes ) ;
assert! ( deserialize_x25519_public ( & [ 0 u8 ; 32 ] ) . is_err ( ) ) ;
}
#[ test ]
fn ed25519_serialization ( ) {
2023-02-27 23:12:24 +00:00
let bytes = [ 0 u8 ; 64 ] ;
2023-03-30 16:13:29 +00:00
let bytes2 = [ 0 u8 ; 32 ] ;
2023-02-27 18:45:02 +00:00
assert_eq! ( deserialize_ed25519_private ( & serialize_ed25519_private ( & bytes ) ) . unwrap ( ) , bytes ) ;
assert! ( deserialize_ed25519_private ( & [ 0 u8 ; 32 ] ) . is_err ( ) ) ;
2023-03-30 16:13:29 +00:00
assert_eq! ( deserialize_ed25519_public ( & serialize_ed25519_public ( & bytes2 ) ) . unwrap ( ) , bytes2 ) ;
assert! ( deserialize_ed25519_public ( & [ 0 u8 ; 64 ] ) . is_err ( ) ) ;
2023-03-29 15:18:33 +00:00
let mut bytes = vec! [ ] ;
2023-03-30 16:13:29 +00:00
bytes . append ( & mut serialize_ed25519_public ( & [ 0 u8 ; 32 ] ) ) ;
bytes . append ( & mut serialize_ed25519_public ( & [ 1 u8 ; 32 ] ) ) ;
2023-03-29 15:18:33 +00:00
let deser = deserialize_ed25519_public_many ( & bytes ) . unwrap ( ) ;
2023-03-30 16:13:29 +00:00
assert_eq! ( deser [ 0 ] , [ 0 u8 ; 32 ] ) ;
assert_eq! ( deser [ 1 ] , [ 1 u8 ; 32 ] ) ;
2023-03-29 15:18:33 +00:00
2023-03-30 16:13:29 +00:00
bytes . append ( & mut serialize_ed25519_public ( & [ 1 u8 ; 33 ] ) ) ;
2023-03-29 15:18:33 +00:00
deserialize_ed25519_public_many ( & bytes ) . unwrap_err ( ) ;
2023-02-27 18:45:02 +00:00
}
#[ test ]
fn cert_verify ( ) {
let ( ca_cert , ca_key , _ca_pub ) = test_ca_cert ( round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 10 ) ) . unwrap ( ) , vec! [ ] , vec! [ ] , vec! [ " groupa " . to_string ( ) ] ) ;
let ( cert , _ , _ ) = test_cert ( & ca_cert , & ca_key , SystemTime ::now ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ ] , vec! [ ] , vec! [ ] ) ;
let mut ca_pool = NebulaCAPool ::new ( ) ;
ca_pool . add_ca_certificate ( & ca_cert . serialize_to_pem ( ) . unwrap ( ) ) . unwrap ( ) ;
let fingerprint = cert . sha256sum ( ) . unwrap ( ) ;
ca_pool . blocklist_fingerprint ( & fingerprint ) ;
assert! ( matches! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::Blocklisted ) ) ;
ca_pool . reset_blocklist ( ) ;
assert! ( matches! ( cert . verify ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 60 ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::RootCertExpired ) ) ;
assert! ( matches! ( cert . verify ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 6 ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::CertExpired ) ) ;
let ( cert_with_bad_group , _ , _ ) = test_cert ( & ca_cert , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , in_a_minute ( ) , vec! [ ] , vec! [ ] , vec! [ " group-not-present on parent " . to_string ( ) ] ) ;
assert_eq! ( cert_with_bad_group . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::GroupNotPresentOnSigner ) ;
let ( cert_with_good_group , _ , _ ) = test_cert ( & ca_cert , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , in_a_minute ( ) , vec! [ ] , vec! [ ] , vec! [ " groupa " . to_string ( ) ] ) ;
assert_eq! ( cert_with_good_group . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::Ok ) ;
}
#[ test ]
fn cert_verify_ip ( ) {
let ca_ip_1 = Ipv4Net ::from_str ( " 10.0.0.0/16 " ) . unwrap ( ) ;
let ca_ip_2 = Ipv4Net ::from_str ( " 192.168.0.0/24 " ) . unwrap ( ) ;
let ( ca , ca_key , _ca_pub ) = test_ca_cert ( round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 10 ) ) . unwrap ( ) , vec! [ ca_ip_1 , ca_ip_2 ] , vec! [ ] , vec! [ ] ) ;
let ca_pem = ca . serialize_to_pem ( ) . unwrap ( ) ;
let mut ca_pool = NebulaCAPool ::new ( ) ;
ca_pool . add_ca_certificate ( & ca_pem ) . unwrap ( ) ;
// ip is outside the network
let cip1 = netmask! ( " 10.1.0.0 " , " 255.255.255.0 " ) ;
let cip2 = netmask! ( " 192.198.0.1 " , " 255.255.0.0 " ) ;
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ cip1 , cip2 ] , vec! [ ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::IPNotPresentOnSigner ) ;
// ip is outside the network - reversed order from above
let cip1 = netmask! ( " 192.198.0.1 " , " 255.255.255.0 " ) ;
let cip2 = netmask! ( " 10.1.0.0 " , " 255.255.255.0 " ) ;
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ cip1 , cip2 ] , vec! [ ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::IPNotPresentOnSigner ) ;
// ip is within the network but mask is outside
let cip1 = netmask! ( " 10.0.1.0 " , " 255.254.0.0 " ) ;
let cip2 = netmask! ( " 192.168.0.1 " , " 255.255.255.0 " ) ;
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ cip1 , cip2 ] , vec! [ ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::IPNotPresentOnSigner ) ;
// ip is within the network but mask is outside - reversed order from above
let cip1 = netmask! ( " 192.168.0.1 " , " 255.255.255.0 " ) ;
let cip2 = netmask! ( " 10.0.1.0 " , " 255.254.0.0 " ) ;
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ cip1 , cip2 ] , vec! [ ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::IPNotPresentOnSigner ) ;
// ip and mask are within the network
let cip1 = netmask! ( " 10.0.1.0 " , " 255.255.0.0 " ) ;
let cip2 = netmask! ( " 192.168.0.1 " , " 255.255.255.128 " ) ;
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ cip1 , cip2 ] , vec! [ ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::Ok ) ;
// Exact matches
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ ca_ip_1 , ca_ip_2 ] , vec! [ ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::Ok ) ;
// Exact matches reversed
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ ca_ip_2 , ca_ip_1 ] , vec! [ ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::Ok ) ;
// Exact matches reversed with just one
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ ca_ip_2 ] , vec! [ ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::Ok ) ;
}
#[ test ]
fn cert_verify_subnet ( ) {
let ca_ip_1 = Ipv4Net ::from_str ( " 10.0.0.0/16 " ) . unwrap ( ) ;
let ca_ip_2 = Ipv4Net ::from_str ( " 192.168.0.0/24 " ) . unwrap ( ) ;
let ( ca , ca_key , _ca_pub ) = test_ca_cert ( round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 10 ) ) . unwrap ( ) , vec! [ ] , vec! [ ca_ip_1 , ca_ip_2 ] , vec! [ ] ) ;
let ca_pem = ca . serialize_to_pem ( ) . unwrap ( ) ;
let mut ca_pool = NebulaCAPool ::new ( ) ;
ca_pool . add_ca_certificate ( & ca_pem ) . unwrap ( ) ;
// ip is outside the network
let cip1 = netmask! ( " 10.1.0.0 " , " 255.255.255.0 " ) ;
let cip2 = netmask! ( " 192.198.0.1 " , " 255.255.0.0 " ) ;
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ ] , vec! [ cip1 , cip2 ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::SubnetNotPresentOnSigner ) ;
// ip is outside the network - reversed order from above
let cip1 = netmask! ( " 192.198.0.1 " , " 255.255.255.0 " ) ;
let cip2 = netmask! ( " 10.1.0.0 " , " 255.255.255.0 " ) ;
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ ] , vec! [ cip1 , cip2 ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::SubnetNotPresentOnSigner ) ;
// ip is within the network but mask is outside
let cip1 = netmask! ( " 10.0.1.0 " , " 255.254.0.0 " ) ;
let cip2 = netmask! ( " 192.168.0.1 " , " 255.255.255.0 " ) ;
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ ] , vec! [ cip1 , cip2 ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::SubnetNotPresentOnSigner ) ;
// ip is within the network but mask is outside - reversed order from above
let cip1 = netmask! ( " 192.168.0.1 " , " 255.255.255.0 " ) ;
let cip2 = netmask! ( " 10.0.1.0 " , " 255.254.0.0 " ) ;
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ cip1 , cip2 ] , vec! [ ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::SubnetNotPresentOnSigner ) ;
// ip and mask are within the network
let cip1 = netmask! ( " 10.0.1.0 " , " 255.255.0.0 " ) ;
let cip2 = netmask! ( " 192.168.0.1 " , " 255.255.255.128 " ) ;
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ ] , vec! [ cip1 , cip2 ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::Ok ) ;
// Exact matches
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ ] , vec! [ ca_ip_1 , ca_ip_2 ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::Ok ) ;
// Exact matches reversed
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ ] , vec! [ ca_ip_2 , ca_ip_1 ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::Ok ) ;
// Exact matches reversed with just one
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , round_systime_to_secs ( SystemTime ::now ( ) ) . unwrap ( ) , round_systime_to_secs ( SystemTime ::now ( ) + Duration ::from_secs ( 60 * 60 * 5 ) ) . unwrap ( ) , vec! [ ] , vec! [ ca_ip_2 ] , vec! [ ] ) ;
assert_eq! ( cert . verify ( SystemTime ::now ( ) , & ca_pool ) . unwrap ( ) , CertificateValidity ::Ok ) ;
}
#[ test ]
fn cert_private_key ( ) {
let ( ca , ca_key , _ ) = test_ca_cert ( SystemTime ::now ( ) , SystemTime ::now ( ) , vec! [ ] , vec! [ ] , vec! [ ] ) ;
ca . verify_private_key ( & ca_key . to_keypair_bytes ( ) ) . unwrap ( ) ;
let ( _ , ca_key2 , _ ) = test_ca_cert ( SystemTime ::now ( ) , SystemTime ::now ( ) , vec! [ ] , vec! [ ] , vec! [ ] ) ;
ca . verify_private_key ( & ca_key2 . to_keypair_bytes ( ) ) . unwrap_err ( ) ;
let ( cert , priv_key , _ ) = test_cert ( & ca , & ca_key , SystemTime ::now ( ) , SystemTime ::now ( ) , vec! [ ] , vec! [ ] , vec! [ ] ) ;
cert . verify_private_key ( & priv_key . to_bytes ( ) ) . unwrap ( ) ;
let ( cert2 , _ , _ ) = test_cert ( & ca , & ca_key , SystemTime ::now ( ) , SystemTime ::now ( ) , vec! [ ] , vec! [ ] , vec! [ ] ) ;
cert2 . verify_private_key ( & priv_key . to_bytes ( ) ) . unwrap_err ( ) ;
}
2023-02-27 19:42:49 +00:00
#[ test ]
fn capool_from_pem ( ) {
let no_newlines = b " # Current provisional, Remove once everything moves over to the real root.
- - - - - BEGIN NEBULA CERTIFICATE - - - - -
CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1 + YGOiCUQGByMuNRhIlQBOyzXWbL
vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
- - - - - END NEBULA CERTIFICATE - - - - -
# root - ca01
- - - - - BEGIN NEBULA CERTIFICATE - - - - -
CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86 + cGOiDPXMH4oU6HZTk / CqTG
BVG + oJpAoqokUBbI4U0N8CSfpUABEkB / Pm5A2xyH / nc8mg / wvGUWG3pZ7nHzaDMf
8 / phAUt + FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
- - - - - END NEBULA CERTIFICATE - - - - - " ;
let with_newlines = b " # Current provisional, Remove once everything moves over to the real root.
- - - - - BEGIN NEBULA CERTIFICATE - - - - -
CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1 + YGOiCUQGByMuNRhIlQBOyzXWbL
vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
- - - - - END NEBULA CERTIFICATE - - - - -
# root - ca01
- - - - - BEGIN NEBULA CERTIFICATE - - - - -
CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86 + cGOiDPXMH4oU6HZTk / CqTG
BVG + oJpAoqokUBbI4U0N8CSfpUABEkB / Pm5A2xyH / nc8mg / wvGUWG3pZ7nHzaDMf
8 / phAUt + FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
- - - - - END NEBULA CERTIFICATE - - - - -
" ;
let expired = b " # expired certificate
- - - - - BEGIN NEBULA CERTIFICATE - - - - -
CjkKB2V4cGlyZWQouPmWjQYwufmWjQY6ILCRaoCkJlqHgv5jfDN4lzLHBvDzaQm4
vZxfu144hmgjQAESQG4qlnZi8DncvD / LDZnLgJHOaX1DWCHHEh59epVsC + BNgTie
WH1M9n4O7cFtGlM6sJJOS + rCVVEJ3ABS7 + MPdQs =
- - - - - END NEBULA CERTIFICATE - - - - - " ;
let pool_a = NebulaCAPool ::new_from_pem ( no_newlines ) . unwrap ( ) ;
assert_eq! ( pool_a . cas [ " c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522 " ] . details . name , " nebula root ca " . to_string ( ) ) ;
assert_eq! ( pool_a . cas [ " 5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd " ] . details . name , " nebula root ca 01 " . to_string ( ) ) ;
assert! ( ! pool_a . expired ) ;
let pool_b = NebulaCAPool ::new_from_pem ( with_newlines ) . unwrap ( ) ;
assert_eq! ( pool_b . cas [ " c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522 " ] . details . name , " nebula root ca " . to_string ( ) ) ;
assert_eq! ( pool_b . cas [ " 5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd " ] . details . name , " nebula root ca 01 " . to_string ( ) ) ;
assert! ( ! pool_b . expired ) ;
let pool_c = NebulaCAPool ::new_from_pem ( expired ) . unwrap ( ) ;
assert! ( pool_c . expired ) ;
assert_eq! ( pool_c . cas [ " 152070be6bb19bc9e3bde4c2f0e7d8f4ff5448b4c9856b8eccb314fade0229b0 " ] . details . name , " expired " ) ;
let mut pool_d = NebulaCAPool ::new_from_pem ( with_newlines ) . unwrap ( ) ;
pool_d . add_ca_certificate ( expired ) . unwrap ( ) ;
assert_eq! ( pool_d . cas [ " c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522 " ] . details . name , " nebula root ca " . to_string ( ) ) ;
assert_eq! ( pool_d . cas [ " 5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd " ] . details . name , " nebula root ca 01 " . to_string ( ) ) ;
assert_eq! ( pool_d . cas [ " 152070be6bb19bc9e3bde4c2f0e7d8f4ff5448b4c9856b8eccb314fade0229b0 " ] . details . name , " expired " ) ;
assert! ( pool_d . expired ) ;
assert_eq! ( pool_d . get_fingerprints ( ) . len ( ) , 3 ) ;
}
2023-02-27 02:58:45 +00:00
#[ macro_export ]
macro_rules ! netmask {
( $ip :expr , $mask :expr ) = > {
Ipv4Net ::with_netmask ( Ipv4Addr ::from_str ( $ip ) . unwrap ( ) , Ipv4Addr ::from_str ( $mask ) . unwrap ( ) ) . unwrap ( )
} ;
2023-02-27 15:04:10 +00:00
}
fn round_systime_to_secs ( time : SystemTime ) -> Result < SystemTime , SystemTimeError > {
let secs = time . duration_since ( UNIX_EPOCH ) ? . as_secs ( ) ;
Ok ( SystemTime ::UNIX_EPOCH . add ( Duration ::from_secs ( secs ) ) )
2023-02-27 18:45:02 +00:00
}
fn test_ca_cert ( before : SystemTime , after : SystemTime , ips : Vec < Ipv4Net > , subnets : Vec < Ipv4Net > , groups : Vec < String > ) -> ( NebulaCertificate , SigningKey , VerifyingKey ) {
let mut csprng = OsRng ;
let key = SigningKey ::generate ( & mut csprng ) ;
let pub_key = key . verifying_key ( ) ;
let mut cert = NebulaCertificate {
details : NebulaCertificateDetails {
name : " TEST_CA " . to_string ( ) ,
ips ,
subnets ,
groups ,
not_before : before ,
not_after : after ,
public_key : pub_key . to_bytes ( ) ,
is_ca : true ,
2023-02-27 23:12:24 +00:00
issuer : String ::new ( ) ,
2023-02-27 18:45:02 +00:00
} ,
signature : vec ! [ ] ,
} ;
cert . sign ( & key ) . unwrap ( ) ;
( cert , key , pub_key )
}
2023-02-27 23:12:24 +00:00
#[ test ]
fn test_deserialize_ed25519_private ( ) {
let priv_key = b " -----BEGIN NEBULA ED25519 PRIVATE KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = =
- - - - - END NEBULA ED25519 PRIVATE KEY - - - - - " ;
let short_key = b " -----BEGIN NEBULA ED25519 PRIVATE KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- - - - - END NEBULA ED25519 PRIVATE KEY - - - - - " ;
let invalid_banner = b " -----BEGIN NOT A NEBULA PRIVATE KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = =
- - - - - END NOT A NEBULA PRIVATE KEY - - - - - " ;
let invalid_pem = b " -BEGIN NEBULA ED25519 PRIVATE KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = =
- END NEBULA ED25519 PRIVATE KEY - - - - - " ;
deserialize_ed25519_private ( priv_key ) . unwrap ( ) ;
deserialize_ed25519_private ( short_key ) . unwrap_err ( ) ;
deserialize_ed25519_private ( invalid_banner ) . unwrap_err ( ) ;
deserialize_ed25519_private ( invalid_pem ) . unwrap_err ( ) ;
}
#[ test ]
fn test_deserialize_x25519_private ( ) {
let priv_key = b " -----BEGIN NEBULA X25519 PRIVATE KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA =
- - - - - END NEBULA X25519 PRIVATE KEY - - - - - " ;
let short_key = b " -----BEGIN NEBULA X25519 PRIVATE KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = =
- - - - - END NEBULA X25519 PRIVATE KEY - - - - - " ;
let invalid_banner = b " -----BEGIN NOT A NEBULA PRIVATE KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA =
- - - - - END NOT A NEBULA PRIVATE KEY - - - - - " ;
let invalid_pem = b " -BEGIN NEBULA X25519 PRIVATE KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA =
- END NEBULA X25519 PRIVATE KEY - - - - - " ;
deserialize_x25519_private ( priv_key ) . unwrap ( ) ;
deserialize_x25519_private ( short_key ) . unwrap_err ( ) ;
deserialize_x25519_private ( invalid_banner ) . unwrap_err ( ) ;
deserialize_x25519_private ( invalid_pem ) . unwrap_err ( ) ;
}
#[ test ]
fn test_pem_deserialization ( ) {
let good_cert = b " # A good cert
- - - - - BEGIN NEBULA CERTIFICATE - - - - -
CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1 + YGOiCUQGByMuNRhIlQBOyzXWbL
vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
- - - - - END NEBULA CERTIFICATE - - - - - " ;
let bad_banner = b " -----BEGIN NOT A NEBULA CERTIFICATE-----
CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1 + YGOiCUQGByMuNRhIlQBOyzXWbL
vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
- - - - - END NOT A NEBULA CERTIFICATE - - - - - " ;
let invalid_pem = b " # Not a valid PEM format
- BEGIN NEBULA CERTIFICATE - - - - -
CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1 + YGOiCUQGByMuNRhIlQBOyzXWbL
vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
- END NEBULA CERTIFICATE - - - - " ;
// success
deserialize_nebula_certificate_from_pem ( good_cert ) . unwrap ( ) ;
// fail because invalid banner
deserialize_nebula_certificate_from_pem ( bad_banner ) . unwrap_err ( ) ;
// fail because nonsense pem
deserialize_nebula_certificate_from_pem ( invalid_pem ) . unwrap_err ( ) ;
}
#[ test ]
fn test_deserialize_ed25519_public ( ) {
2023-03-30 16:13:29 +00:00
let pub_key = b " -----BEGIN NEBULA ED25519 PUBLIC KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA =
2023-02-27 23:12:24 +00:00
- - - - - END NEBULA ED25519 PUBLIC KEY - - - - - " ;
let short_key = b " -----BEGIN NEBULA ED25519 PUBLIC KEY-----
2023-03-30 16:13:29 +00:00
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA =
2023-02-27 23:12:24 +00:00
- - - - - END NEBULA ED25519 PUBLIC KEY - - - - - " ;
let invalid_banner = b " -----BEGIN NOT A NEBULA PUBLIC KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = =
- - - - - END NOT A NEBULA PUBLIC KEY - - - - - " ;
let invalid_pem = b " -BEGIN NEBULA ED25519 PUBLIC KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = =
- END NEBULA ED25519 PUBLIC KEY - - - - - " ;
2023-03-30 16:13:29 +00:00
deserialize_ed25519_public ( pub_key ) . unwrap ( ) ;
2023-02-27 23:12:24 +00:00
deserialize_ed25519_public ( short_key ) . unwrap_err ( ) ;
deserialize_ed25519_public ( invalid_banner ) . unwrap_err ( ) ;
deserialize_ed25519_public ( invalid_pem ) . unwrap_err ( ) ;
}
#[ test ]
// Ensure that trifid-pki produces the *exact same* bit-for-bit representation as nebula does
// to ensure signature interoperability
// We use an e3team production certificate for this as it is a known-good certificate.
fn test_serialization_interoperability ( ) {
let known_good_cert = hex ::decode ( " 0a650a08636f72652d74777212098184c4508080f8ff0f28ae9fbf9c06309485c4ab063a20304e6279d8722f0fd8d966faa70adaeec08c4649d486457bb038be243753a7474a2056860ded3d14b7f3b77ca2a062ee5d683dd06b35f87446d8d6a7e923b6a7783d1240eb5d6b688eda0d36e925219c098ff2799e42207a093f7d9b7d875823ca05b2e0d3a749dd2fc9cec811ed9a2865d71c4d53cfdfd1bf7e6d5058bd9ecd388ddf0d " ) . unwrap ( ) ;
let cert = deserialize_nebula_certificate ( & known_good_cert ) . unwrap ( ) ;
let reserialized_cert_pem = cert . serialize ( ) . unwrap ( ) ;
assert_eq! ( known_good_cert , reserialized_cert_pem ) ;
}
#[ test ]
fn test_deserialize_x25519_public ( ) {
let priv_key = b " -----BEGIN NEBULA X25519 PUBLIC KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA =
- - - - - END NEBULA X25519 PUBLIC KEY - - - - - " ;
let short_key = b " -----BEGIN NEBULA X25519 PUBLIC KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = =
- - - - - END NEBULA X25519 PUBLIC KEY - - - - - " ;
let invalid_banner = b " -----BEGIN NOT A NEBULA PUBLIC KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA =
- - - - - END NOT A NEBULA PUBLIC KEY - - - - - " ;
let invalid_pem = b " -BEGIN NEBULA X25519 PUBLIC KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA =
- END NEBULA X25519 PUBLIC KEY - - - - - " ;
deserialize_x25519_public ( priv_key ) . unwrap ( ) ;
deserialize_x25519_public ( short_key ) . unwrap_err ( ) ;
deserialize_x25519_public ( invalid_banner ) . unwrap_err ( ) ;
deserialize_x25519_public ( invalid_pem ) . unwrap_err ( ) ;
}
#[ test ]
fn ca_pool_add_non_ca ( ) {
let mut ca_pool = NebulaCAPool ::new ( ) ;
let ( ca , ca_key , _ ) = test_ca_cert ( SystemTime ::now ( ) , SystemTime ::now ( ) + Duration ::from_secs ( 3600 ) , vec! [ ] , vec! [ ] , vec! [ ] ) ;
let ( cert , _ , _ ) = test_cert ( & ca , & ca_key , SystemTime ::now ( ) , SystemTime ::now ( ) , vec! [ ] , vec! [ ] , vec! [ ] ) ;
ca_pool . add_ca_certificate ( & cert . serialize_to_pem ( ) . unwrap ( ) ) . unwrap_err ( ) ;
}
2023-02-27 18:45:02 +00:00
fn test_cert ( ca : & NebulaCertificate , key : & SigningKey , before : SystemTime , after : SystemTime , ips : Vec < Ipv4Net > , subnets : Vec < Ipv4Net > , groups : Vec < String > ) -> ( NebulaCertificate , SigningKey , VerifyingKey ) {
let issuer = ca . sha256sum ( ) . unwrap ( ) ;
let real_groups = if groups . is_empty ( ) {
vec! [ " test-group1 " . to_string ( ) , " test-group2 " . to_string ( ) , " test-group3 " . to_string ( ) ]
} else {
groups
} ;
let real_ips = if ips . is_empty ( ) {
vec! [
netmask! ( " 10.1.1.1 " , " 255.255.255.0 " ) ,
netmask! ( " 10.1.1.2 " , " 255.255.0.0 " ) ,
netmask! ( " 10.1.1.3 " , " 255.0.0.0 " )
]
} else {
ips
} ;
let real_subnets = if subnets . is_empty ( ) {
vec! [
netmask! ( " 9.1.1.1 " , " 255.255.255.128 " ) ,
netmask! ( " 9.1.1.2 " , " 255.255.255.0 " ) ,
netmask! ( " 9.1.1.3 " , " 255.255.0.0 " )
]
} else {
subnets
} ;
let mut csprng = OsRng ;
let cert_key = SigningKey ::generate ( & mut csprng ) ;
let pub_key = cert_key . verifying_key ( ) ;
let mut cert = NebulaCertificate {
details : NebulaCertificateDetails {
name : " TEST_CA " . to_string ( ) ,
ips : real_ips ,
subnets : real_subnets ,
groups : real_groups ,
not_before : before ,
not_after : after ,
public_key : pub_key . to_bytes ( ) ,
is_ca : false ,
issuer ,
} ,
signature : vec ! [ ] ,
} ;
cert . sign ( key ) . unwrap ( ) ;
( cert , cert_key , pub_key )
}
#[ allow(dead_code) ]
fn in_a_minute ( ) -> SystemTime {
round_systime_to_secs ( SystemTime ::now ( ) . add ( Duration ::from_secs ( 60 ) ) ) . unwrap ( )
}
#[ allow(dead_code) ]
fn a_minute_ago ( ) -> SystemTime {
round_systime_to_secs ( SystemTime ::now ( ) . sub ( Duration ::from_secs ( 60 ) ) ) . unwrap ( )
2023-02-27 02:58:45 +00:00
}