Skip to content

Commit

Permalink
monero: only mask user features on new polyseed, not on decode
Browse files Browse the repository at this point in the history
- This commit ensures a polyseed string that has unsupported features correctly errors on decode (rather than panic in debug build or return an incorrect successful response in prod build)
- Also avoids panicking when checksum calculation is unexpectedly wrong

Polyseed reference impl for feature masking:
- polyseed_create: https://github.com/tevador/polyseed/blob/b7c35bb3c6b91e481ecb04fc235eaff69c507fa1/src/polyseed.c#L61
- polyseed_decode: https://github.com/tevador/polyseed/blob/b7c35bb3c6b91e481ecb04fc235eaff69c507fa1/src/polyseed.c#L212
  • Loading branch information
j-berman committed Jan 3, 2024
1 parent 6c8040f commit c30b6be
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 17 deletions.
11 changes: 10 additions & 1 deletion coins/monero/src/tests/seed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use curve25519_dalek::scalar::Scalar;
use crate::{
hash,
wallet::seed::{
Seed, SeedType,
Seed, SeedType, SeedError,
classic::{self, trim_by_lang},
polyseed,
},
Expand Down Expand Up @@ -405,3 +405,12 @@ fn test_polyseed() {
}
}
}

#[test]
fn test_invalid_polyseed() {
let seed = "include domain claim resemble urban hire lunch bird \
crucial fire best wife ring warm ignore model"
.into();
let res = Seed::from_string(Zeroizing::new(seed));
assert_eq!(res, Err(SeedError::UnsupportedFeatures));
}
47 changes: 31 additions & 16 deletions coins/monero/src/wallet/seed/polyseed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,31 @@ fn valid_entropy(entropy: &Zeroizing<[u8; 32]>) -> bool {
res.into()
}

fn from_internal(
language: Language,
masked_features: u8,
encoded_birthday: u16,
entropy: Zeroizing<[u8; 32]>,
) -> Result<Polyseed, SeedError> {
if !polyseed_features_supported(masked_features) {
Err(SeedError::UnsupportedFeatures)?;
}

if !valid_entropy(&entropy) {
Err(SeedError::InvalidEntropy)?;
}

let mut res = Polyseed {
language,
birthday: encoded_birthday,
features: masked_features,
entropy,
checksum: 0,
};
res.checksum = poly_eval(&res.to_poly());
Ok(res)
}

impl Polyseed {
// TODO: Clean this
fn to_poly(&self) -> Poly {
Expand Down Expand Up @@ -226,20 +251,7 @@ impl Polyseed {
birthday: u64,
entropy: Zeroizing<[u8; 32]>,
) -> Result<Polyseed, SeedError> {
let features = user_features(features);
if !polyseed_features_supported(features) {
Err(SeedError::UnsupportedFeatures)?;
}

let birthday = birthday_encode(birthday);

if !valid_entropy(&entropy) {
Err(SeedError::InvalidEntropy)?;
}

let mut res = Polyseed { language, birthday, features, entropy, checksum: 0 };
res.checksum = poly_eval(&res.to_poly());
Ok(res)
from_internal(language, user_features(features), birthday_encode(birthday), entropy)
}

/// Create a new `Polyseed`.
Expand Down Expand Up @@ -375,9 +387,12 @@ impl Polyseed {
let features =
u8::try_from(extra >> DATE_BITS).expect("couldn't convert extra >> DATE_BITS to u8");

let res = Polyseed::from(lang, features, birthday_decode(birthday), entropy);
let res = from_internal(lang, features, birthday, entropy);
if let Ok(res) = res.as_ref() {
debug_assert_eq!(res.checksum, checksum);
if res.checksum != checksum {
// This should never trigger
Err(SeedError::InvalidSeed)?;
}
}
res
}
Expand Down

0 comments on commit c30b6be

Please sign in to comment.