Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disallow setting FactorSource for ROLA to one with an unsupported/dis… #313

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
c91f8f6
Reintroduce `From<RoleWithFactorInstances<ROLE>> for ScryptoAccessRule`
CyonAlexRDX Dec 6, 2024
2d3259e
impl From<MatrixOfFactorInstances> for ScryptoRuleSet
CyonAlexRDX Dec 9, 2024
502ba59
Merge branch 'main' into scrypto_access_rules_for_matrix_of_factor_in…
CyonAlexRDX Dec 12, 2024
7eb9e2d
bump Scrypto and RET
CyonAlexRDX Dec 12, 2024
4f39117
[no ci] WIP
Sajjon Dec 12, 2024
bf57732
[no ci] WIP
Sajjon Dec 12, 2024
ed7f78d
[no ci] wip
CyonAlexRDX Dec 13, 2024
9f7790d
create_access_controller
Sajjon Dec 13, 2024
332c6a9
[no ci] WIP
Sajjon Dec 13, 2024
9cded45
[no ci] wip
CyonAlexRDX Dec 13, 2024
8faaf3e
merge
Sajjon Dec 15, 2024
5efcfff
[no ci] WIP
Sajjon Dec 16, 2024
20fccd0
[no ci] wip
CyonAlexRDX Dec 16, 2024
f2ba3fa
[no ci] WIP
Sajjon Dec 16, 2024
642c9cc
[no ci] WIP
Sajjon Dec 16, 2024
d68c597
update readme
Sajjon Dec 16, 2024
9c8e7bc
fix swift
CyonAlexRDX Dec 16, 2024
6e56fa2
doc
CyonAlexRDX Dec 16, 2024
a0f3e6a
removed unused code
CyonAlexRDX Dec 16, 2024
15200f5
more tests
Sajjon Dec 16, 2024
67bc386
[no ci] WIP
Sajjon Dec 17, 2024
e54a5d3
polish
Sajjon Dec 17, 2024
3ba71d3
fix typo
Sajjon Dec 17, 2024
5940db0
Merge branch 'scrypto_access_rules_for_matrix_of_factor_instances' in…
Sajjon Dec 17, 2024
a2f77c8
[no ci] WIP
Sajjon Dec 17, 2024
48a568f
Merge branch 'main' into ac/mix_persona_and_accounts_in_factor_instan…
Sajjon Dec 17, 2024
ce3e9fd
[no ci] WIP
Sajjon Dec 17, 2024
01288fa
[no ci] WIP
Sajjon Dec 17, 2024
48874f9
wip
Sajjon Dec 17, 2024
f5319b1
[no ci] WIP
Sajjon Dec 17, 2024
ed84dba
[no ci] WIP
Sajjon Dec 17, 2024
8da5a2d
[no ci] WIP
Sajjon Dec 17, 2024
9a367a4
[no ci] WIP
Sajjon Dec 17, 2024
59d597f
[no ci] WIP
Sajjon Dec 17, 2024
e3de138
[no ci] WIP
Sajjon Dec 17, 2024
c0e0b42
[no ci] WIP
Sajjon Dec 17, 2024
2dc1484
[no ci] WIP
Sajjon Dec 17, 2024
64c17f8
[no ci] WIP
Sajjon Dec 18, 2024
4b477c6
[no ci] WIP
Sajjon Dec 18, 2024
8ae342f
[no ci] WIP
Sajjon Dec 18, 2024
1da8628
[no ci] WIP
Sajjon Dec 18, 2024
22c5855
[no ci] WIP
Sajjon Dec 18, 2024
41b1a11
[no ci] WIP
Sajjon Dec 18, 2024
4b8c041
[no ci] WIP
Sajjon Dec 18, 2024
ccf46b6
[no ci] WIP
Sajjon Dec 18, 2024
8e4c576
[no ci] WIP
Sajjon Dec 18, 2024
f269392
[no ci] WIP
Sajjon Dec 18, 2024
e8ff22f
[no ci] WIP
Sajjon Dec 18, 2024
632f907
[no ci] WIP
Sajjon Dec 18, 2024
9d89a31
clippy fix
Sajjon Dec 18, 2024
93bc314
remove prints
Sajjon Dec 18, 2024
18009fa
merge main
Sajjon Dec 18, 2024
d67aea5
add ROLA key to builder
Sajjon Dec 19, 2024
1ff2f54
fix failing tests (the hard ones - JSON remain... easy)
Sajjon Dec 19, 2024
b2ca5b9
fix all tests
Sajjon Dec 19, 2024
cd456d2
fixes
Sajjon Dec 19, 2024
e8d16d6
fix swift tests
Sajjon Dec 19, 2024
6715385
fmt
CyonAlexRDX Dec 19, 2024
5e29d97
Merge branch 'main' into ac/mix_persona_and_accounts_in_factor_instan…
Sajjon Dec 20, 2024
3a21681
merge
Sajjon Dec 20, 2024
d69166b
__OFFLINE_ONLY_securify_entities
CyonAlexRDX Dec 20, 2024
a8146bb
[no ci] WIP
Sajjon Dec 20, 2024
92fe297
fix last test
Sajjon Dec 20, 2024
8d0d109
add more tests
Sajjon Dec 20, 2024
717cd3d
Disallow setting FactorSource for ROLA to one with an unsupported/dis…
Sajjon Dec 20, 2024
4d0b9ab
review fixes
Sajjon Dec 20, 2024
ee84209
review polish
Sajjon Dec 20, 2024
bbe7a30
Merge branch 'ac/mix_persona_and_accounts_in_factor_instances_provide…
Sajjon Dec 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ struct ShieldTests {

#expect(builder.validate() == .ConfirmationRoleMustHaveAtLeastOneFactor)
builder.addFactorSourceToConfirmationOverride(factorSourceId: .sampleArculus)

builder.setAuthenticationSigningFactor(new: .sampleDevice)

#expect(builder.validate() == nil)
#expect((try? builder.build()) != nil)
}
Expand Down Expand Up @@ -173,6 +176,8 @@ struct ShieldTests {
builder.addFactorSourceToRecoveryOverride(factorSourceId: .sampleArculus)
builder.addFactorSourceToConfirmationOverride(factorSourceId: .sampleArculusOther)

builder.setAuthenticationSigningFactor(new: .sampleDevice)

let shield = try! builder.build()

#expect(shield.matrixOfFactors.primaryRole.overrideFactors.isEmpty)
Expand Down Expand Up @@ -205,6 +210,8 @@ struct ShieldTests {
builder.removeFactorFromPrimary(factorSourceId: .sampleArculusOther)
builder.removeFactorFromRecovery(factorSourceId: .sampleLedgerOther)

builder.setAuthenticationSigningFactor(new: .sampleDevice)

// Validate
#expect(builder.validate() == nil)

Expand Down
2 changes: 1 addition & 1 deletion crates/sargon-uniffi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "sargon-uniffi"
# Don't forget to update version in crates/sargon/Cargo.toml
version = "1.1.92"
version = "1.1.93"
edition = "2021"
build = "build.rs"

Expand Down
9 changes: 9 additions & 0 deletions crates/sargon-uniffi/src/core/error/common_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,15 @@ pub enum CommonError {

#[error("Cannot securify entity that has provisional security config")]
CannotSecurifyEntityHasProvisionalSecurityConfig = 10241,

#[error("Too few FactorInstances derived")]
TooFewFactorInstancesDerived = 10242,

#[error("Missing Authentication Signing FactorInstance mapping SecurityStructureOfFactorSources into SecurityStructureOfFactorInstances.")]
MissingRolaKeyForSecurityStructureOfFactorInstances = 10243,

#[error("SecurityStateAccessController address mismatch")]
SecurityStateAccessControllerAddressMismatch = 10244,
}

#[uniffi::export]
Expand Down
4 changes: 4 additions & 0 deletions crates/sargon-uniffi/src/keys_collector/derivation_purpose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ pub enum DerivationPurpose {
/// for identity MFA
SecurifyingPersona,

/// When applying a security shield to accounts and personas mixed, initiates keys collection
/// for account MFA
SecurifyingAccountsAndPersonas,

/// When adding a new factor source, initiates keys collection
/// for collecting various factor instances.
PreDerivingKeys,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ impl SecurityShieldBuilder {
self.get(|builder| builder.get_name())
}

pub fn get_authentication_signing_factor(&self) -> Option<FactorSourceID> {
self.get(|builder| builder.get_authentication_signing_factor())
.map(|x| x.into())
}

pub fn get_primary_threshold_factors(&self) -> Vec<FactorSourceID> {
self.get_factors(|builder| builder.get_primary_threshold_factors())
}
Expand All @@ -135,6 +140,17 @@ impl SecurityShieldBuilder {
self.set(|builder| builder.set_name(&name));
}

pub fn set_authentication_signing_factor(
&self,
new: Option<FactorSourceID>,
) {
self.set(|builder| {
builder.set_authentication_signing_factor(
new.clone().map(|x| x.into_internal()),
)
});
}

pub fn remove_factor_from_all_roles(
&self,
factor_source_id: FactorSourceID,
Expand Down Expand Up @@ -236,6 +252,29 @@ impl SecurityShieldBuilder {

#[uniffi::export]
impl SecurityShieldBuilder {
/// "Statically" queries which FactorSourceKinds are disallowed for authentication signing.
pub fn disallowed_factor_source_kinds_for_authentication_signing(
&self,
) -> Vec<FactorSourceKind> {
sargon::SecurityShieldBuilder::disallowed_factor_source_kinds_for_authentication_signing().into_type()
}

/// "Statically" queries which FactorSourceKinds are allowed for authentication signing.
pub fn allowed_factor_source_kinds_for_authentication_signing(
&self,
) -> Vec<FactorSourceKind> {
sargon::SecurityShieldBuilder::allowed_factor_source_kinds_for_authentication_signing().into_type()
}

/// "Statically" queries if `factor_source_kind`` is allowed for authentication signing.
pub fn is_allowed_factor_source_kind_for_authentication_signing(
&self,
factor_source_kind: FactorSourceKind,
) -> bool {
sargon::SecurityShieldBuilder::is_allowed_factor_source_kind_for_authentication_signing(
factor_source_kind.clone().into())
}

pub fn addition_of_factor_source_of_kind_to_primary_threshold_is_fully_valid(
&self,
factor_source_kind: FactorSourceKind,
Expand Down Expand Up @@ -545,6 +584,35 @@ mod tests {
#[allow(clippy::upper_case_acronyms)]
type SUT = SecurityShieldBuilder;

#[test]
fn rola() {
let sut = SUT::new();
assert_eq!(sut.disallowed_factor_source_kinds_for_authentication_signing().len(), sargon::SecurityShieldBuilder::disallowed_factor_source_kinds_for_authentication_signing().len());

assert_eq!(sut.allowed_factor_source_kinds_for_authentication_signing().len(), sargon::SecurityShieldBuilder::allowed_factor_source_kinds_for_authentication_signing().len());

assert!(
sut.is_allowed_factor_source_kind_for_authentication_signing(
FactorSourceKind::Device
)
);
assert!(
!sut.is_allowed_factor_source_kind_for_authentication_signing(
FactorSourceKind::Password
)
);
assert!(
!sut.is_allowed_factor_source_kind_for_authentication_signing(
FactorSourceKind::TrustedContact
)
);
assert!(
!sut.is_allowed_factor_source_kind_for_authentication_signing(
FactorSourceKind::SecurityQuestions
)
);
}

#[test]
fn test() {
let sut = SUT::new();
Expand Down Expand Up @@ -756,6 +824,18 @@ mod tests {
sut.remove_factor_from_confirmation(f.clone());
assert_eq!(xs, sut.get_confirmation_factors());

assert_eq!(
sut.validate().unwrap(),
SecurityShieldBuilderInvalidReason::MissingAuthSigningFactor
);
sut.set_authentication_signing_factor(Some(
FactorSourceID::sample_device_other(),
));
assert_eq!(
sut.get_authentication_signing_factor(),
Some(FactorSourceID::sample_device_other())
);

let v0 = sut.validate();
let v1 = sut.validate(); // can call validate many times!
assert_eq!(v0, v1);
Expand All @@ -764,6 +844,10 @@ mod tests {
let shield = sut.build().unwrap(); // can call build many times!
assert_eq!(shield0, shield);

assert_eq!(
shield.authentication_signing_factor,
FactorSourceID::sample_device_other()
);
assert_eq!(shield.metadata.display_name.value, "S.H.I.E.L.D.");
assert_eq!(
shield.matrix_of_factors.primary_role.override_factors,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use thiserror::Error as ThisError;
Clone, Debug, ThisError, PartialEq, InternalConversion, uniffi::Error,
)]
pub enum SecurityShieldBuilderInvalidReason {
#[error("Auth Signing Factor Missing")]
MissingAuthSigningFactor,

#[error("Shield name is invalid")]
ShieldNameInvalid,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ pub struct SecurityStructureOfFactorSourceIDs {
/// The structure of factors to use for certain roles, Primary, Recovery
/// and Confirmation role.
pub matrix_of_factors: MatrixOfFactorSourceIDs,

/// The factor to use for authentication signing aka true Rola Key.
pub authentication_signing_factor: FactorSourceID,
}

delegate_debug_into!(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ pub struct SecurityStructureOfFactorSources {
/// The structure of factors to use for certain roles, Primary, Recovery
/// and Confirmation role.
pub matrix_of_factors: MatrixOfFactorSources,

/// The factor to use for authentication signing aka true Rola Key.
pub authentication_signing_factor: FactorSource,
}

#[uniffi::export]
Expand Down
2 changes: 1 addition & 1 deletion crates/sargon/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "sargon"
# Don't forget to update version in crates/sargon-uniffi/Cargo.toml
version = "1.1.92"
version = "1.1.93"
edition = "2021"
build = "build.rs"

Expand Down
9 changes: 9 additions & 0 deletions crates/sargon/src/core/error/common_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,15 @@ pub enum CommonError {

#[error("Cannot securify entity that has provisional security config")]
CannotSecurifyEntityHasProvisionalSecurityConfig = 10241,

#[error("Too few FactorInstances derived")]
TooFewFactorInstancesDerived = 10242,

#[error("Missing Authentication Signing FactorInstance mapping SecurityStructureOfFactorSources into SecurityStructureOfFactorInstances.")]
MissingRolaKeyForSecurityStructureOfFactorInstances = 10243,

#[error("SecurityStateAccessController address mismatch")]
SecurityStateAccessControllerAddressMismatch = 10244,
}

impl CommonError {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ mod tests {
fn public_key() {
let private_key = SUT::sample();
let public_key = private_key.public_key();
println!("{:?}", public_key);
assert_eq!(
public_key,
KeyAgreementPublicKey::from_hex("8679bc1fe3210b2ce84793668b05218fdc4c220bc05387b7d2ac0d4c7b7c5d10".to_owned())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ pub enum DerivationPreset {
#[debug("A-MFA")]
AccountMfa,

/// Used to form DerivationPaths used to derive FactorInstances
/// for Authentication Signing (Securified) for accounts
/// `(EntityKind::Account, KeySpace::Securified, KeyKind::AuthenticationSigning)`
#[debug("A-Rola")]
AccountRola,

/// Used to form DerivationPaths used to derive FactorInstances
/// for "veci": Virtual Entity Creating (Factor)Instance for personas.
/// `(EntityKind::Identity, KeySpace::Unsecurified, KeyKind::TransactionSigning)`
Expand All @@ -35,6 +41,12 @@ pub enum DerivationPreset {
/// `(EntityKind::Identity, KeySpace::Securified, KeyKind::TransactionSigning)`
#[debug("I-MFA")]
IdentityMfa,

/// Used to form DerivationPaths used to derive FactorInstances
/// for Authentication Signing (Securified) for peresonas
/// `(EntityKind::Identity, KeySpace::Securified, KeyKind::AuthenticationSigning)`
#[debug("I-Rola")]
IdentityRola,
}

// =============
Expand Down Expand Up @@ -63,6 +75,15 @@ impl DerivationPreset {
CAP26EntityKind::Identity => Self::IdentityMfa,
}
}

/// Selects a `DerivationPreset` for MFA based on `CAP26EntityKind`,
/// i.e. either `DerivationPreset::AccountRola` or `DerivationPreset::IdentityRola`.
pub fn rola_entity_kind(entity_kind: CAP26EntityKind) -> Self {
match entity_kind {
CAP26EntityKind::Account => Self::AccountRola,
CAP26EntityKind::Identity => Self::IdentityRola,
}
}
}

// =============
Expand All @@ -72,8 +93,12 @@ impl DerivationPreset {
/// Returns the `CAP26EntityKind` of the `DerivationPreset`.
pub fn entity_kind(&self) -> CAP26EntityKind {
match self {
Self::AccountVeci | Self::AccountMfa => CAP26EntityKind::Account,
Self::IdentityVeci | Self::IdentityMfa => CAP26EntityKind::Identity,
Self::AccountVeci | Self::AccountMfa | Self::AccountRola => {
CAP26EntityKind::Account
}
Self::IdentityVeci | Self::IdentityMfa | Self::IdentityRola => {
CAP26EntityKind::Identity
}
}
}

Expand All @@ -84,6 +109,9 @@ impl DerivationPreset {
| Self::IdentityVeci
| Self::AccountMfa
| Self::IdentityMfa => CAP26KeyKind::TransactionSigning,
Self::AccountRola | Self::IdentityRola => {
CAP26KeyKind::AuthenticationSigning
}
}
}

Expand All @@ -96,7 +124,10 @@ impl DerivationPreset {
is_hardened: true,
}
}
Self::AccountMfa | Self::IdentityMfa => KeySpace::Securified,
Self::AccountMfa
| Self::IdentityMfa
| Self::AccountRola
| Self::IdentityRola => KeySpace::Securified,
}
}

Expand Down Expand Up @@ -136,4 +167,28 @@ mod tests {
fn inequality() {
assert_ne!(SUT::sample(), SUT::sample_other());
}

#[test]
fn test_mfa_entity_kind() {
assert_eq!(
SUT::mfa_entity_kind(CAP26EntityKind::Account),
SUT::AccountMfa
);
assert_eq!(
SUT::mfa_entity_kind(CAP26EntityKind::Identity),
SUT::IdentityMfa
);
}

#[test]
fn test_rola_entity_kind() {
assert_eq!(
SUT::rola_entity_kind(CAP26EntityKind::Account),
SUT::AccountRola
);
assert_eq!(
SUT::rola_entity_kind(CAP26EntityKind::Identity),
SUT::IdentityRola
);
}
}
Loading
Loading