cryptohome: Set auth_locked policy to false when PIN is reset.
The auth_locked policy must explicitly be set to false for Chrome to
recognize the PIN is usable after a reset.
Cherry picked from
https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2994464
BUG=chromium:1224150
TEST=Lock out PIN and use password
Change-Id: I06896c23be7ceccbaea88f48001f25c752c43d64
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3002282
Reviewed-by: Daniil Lunev <dlunev@chromium.org>
Commit-Queue: Greg Kerr OOO <kerrnel@chromium.org>
Tested-by: Greg Kerr OOO <kerrnel@chromium.org>
Auto-Submit: Greg Kerr OOO <kerrnel@chromium.org>
diff --git a/cryptohome/crypto_unittest.cc b/cryptohome/crypto_unittest.cc
index 65cc3c6..2aa0b64 100644
--- a/cryptohome/crypto_unittest.cc
+++ b/cryptohome/crypto_unittest.cc
@@ -844,4 +844,32 @@
EXPECT_EQ(CryptoError::CE_NONE, crypto_error);
}
+// crbug.com/1224150: auth_locked must be set to false when an LE credential is
+// re-saved.
+TEST_F(LeCredentialsManagerTest, EncryptTestReset) {
+ EXPECT_CALL(*le_cred_manager_, InsertCredential(_, _, _, _, _, _))
+ .WillOnce(Return(LE_CRED_SUCCESS));
+
+ pin_vault_keyset_.CreateRandom();
+ pin_vault_keyset_.SetLowEntropyCredential(true);
+
+ // This used to happen in VaultKeyset::EncryptVaultKeyset, but now happens in
+ // VaultKeyset::Encrypt and thus needs to be done manually here.
+ pin_vault_keyset_.reset_seed_ =
+ CryptoLib::CreateSecureRandomBlob(kAesBlockSize);
+ pin_vault_keyset_.reset_salt_ =
+ CryptoLib::CreateSecureRandomBlob(kAesBlockSize);
+ pin_vault_keyset_.reset_secret_ = CryptoLib::HmacSha256(
+ pin_vault_keyset_.reset_salt_.value(), pin_vault_keyset_.reset_seed_);
+ pin_vault_keyset_.auth_locked_ = true;
+
+ SecureBlob key("key");
+ EXPECT_TRUE(pin_vault_keyset_.Encrypt(key, "foo@gmail.com"));
+ EXPECT_TRUE(pin_vault_keyset_.HasKeyData());
+ EXPECT_FALSE(pin_vault_keyset_.auth_locked_);
+
+ const SerializedVaultKeyset& serialized = pin_vault_keyset_.ToSerialized();
+ EXPECT_FALSE(serialized.key_data().policy().auth_locked());
+}
+
} // namespace cryptohome
diff --git a/cryptohome/vault_keyset.cc b/cryptohome/vault_keyset.cc
index f8e905a..d6362d5 100644
--- a/cryptohome/vault_keyset.cc
+++ b/cryptohome/vault_keyset.cc
@@ -429,6 +429,13 @@
reset_salt_ = CryptoLib::CreateSecureRandomBlob(kAesBlockSize);
reset_secret_ = CryptoLib::HmacSha256(reset_salt_.value(), reset_seed_);
+
+ // crbug.com/1224150: When an LE credential is resaved, that means the user
+ // authenticated successfully. In this case, auth_locked policy must always
+ // be set to false. Otherwise when a user enters their password, and
+ // PinWeaver unlocks the LE Credential, this field will remain set to true
+ // and PIN is never usable by Chrome.
+ auth_locked_ = false;
}
AuthBlockState auth_block_state;
@@ -461,7 +468,7 @@
}
std::string VaultKeyset::GetLabel() const {
- if (key_data_.has_value()) {
+ if (key_data_.has_value() & !key_data_->label().empty()) {
return key_data_->label();
}
// Fallback for legacy keys, for which the label has to be inferred from the
@@ -758,10 +765,8 @@
*(serialized.mutable_key_data()) = key_data_.value();
}
- if (auth_locked_) {
- serialized.mutable_key_data()->mutable_policy()->set_auth_locked(
- auth_locked_);
- }
+ serialized.mutable_key_data()->mutable_policy()->set_auth_locked(
+ auth_locked_);
if (wrapped_chaps_key_.has_value()) {
serialized.set_wrapped_chaps_key(wrapped_chaps_key_->data(),
diff --git a/cryptohome/vault_keyset.h b/cryptohome/vault_keyset.h
index 2947ca7..3ee61b5 100644
--- a/cryptohome/vault_keyset.h
+++ b/cryptohome/vault_keyset.h
@@ -325,6 +325,7 @@
FRIEND_TEST_ALL_PREFIXES(CryptoTest, ScryptStepTest);
FRIEND_TEST_ALL_PREFIXES(LeCredentialsManagerTest, Encrypt);
FRIEND_TEST_ALL_PREFIXES(LeCredentialsManagerTest, EncryptFail);
+ FRIEND_TEST_ALL_PREFIXES(LeCredentialsManagerTest, EncryptTestReset);
};
} // namespace cryptohome