Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Unified Diff: mount.cc

Issue 2645008: Update on feedback, update dbus API, add unit tests. TEST=manual,unit,BVT BUG=3628 323 (Closed) Base URL: ssh://git@chromiumos-git/cryptohome.git
Patch Set: Address second round of feedback. Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mount.h ('k') | mount_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mount.cc
diff --git a/mount.cc b/mount.cc
index c1eabefcddb1284e5d9683295a7c5f8ad07e27cb..47bb05207c8e3f4b593c172365c84ac936114ce7 100644
--- a/mount.cc
+++ b/mount.cc
@@ -4,74 +4,46 @@
// Contains the implementation of class Mount
-// TODO(fes): Use correct ordering of file includes once the platform-specific
-// calls are moved into a separate file. Right now, this is required in order
-// to avoid redefinitions.
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/platform_thread.h"
-#include "base/time.h"
-#include "base/string_util.h"
-#include "chromeos/utility.h"
-#include "cryptohome/cryptohome_common.h"
-#include "cryptohome/mount.h"
-#include "cryptohome/username_passkey.h"
-
-extern "C" {
-#include <ecryptfs.h>
-#include <keyutils.h>
-}
-#include <dirent.h>
+#include "mount.h"
+
#include <errno.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/rand.h>
-#include <openssl/sha.h>
-#include <pwd.h>
-#include <signal.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
+
+#include <base/file_util.h>
+#include <base/logging.h>
+#include <base/platform_thread.h>
+#include <base/time.h>
+#include <base/string_util.h>
+#include <chromeos/utility.h>
+
+#include "crypto.h"
+#include "cryptohome_common.h"
+#include "platform.h"
+#include "username_passkey.h"
using std::string;
namespace cryptohome {
-const string kDefaultEntropySource = "/dev/urandom";
-const string kDefaultHomeDir = "/home/chronos/user";
-const int kDefaultMountOptions = MS_NOEXEC | MS_NOSUID | MS_NODEV;
-const string kDefaultShadowRoot = "/home/.shadow";
-const string kDefaultSharedUser = "chronos";
-const string kDefaultSkeletonSource = "/etc/skel";
-const string kIncognitoUser = "incognito";
-const string kMtab = "/etc/mtab";
-const string kOpenSSLMagic = "Salted__";
-const std::string kProcDir = "/proc";
+const std::string kDefaultHomeDir = "/home/chronos/user";
+const std::string kDefaultShadowRoot = "/home/.shadow";
+const std::string kDefaultSharedUser = "chronos";
+const std::string kDefaultSkeletonSource = "/etc/skel";
+// TODO(fes): Remove once UI for BWSI switches to MountGuest()
+const std::string kIncognitoUser = "incognito";
Mount::Mount()
: default_user_(-1),
default_group_(-1),
default_username_(kDefaultSharedUser),
- entropy_source_(kDefaultEntropySource),
home_dir_(kDefaultHomeDir),
shadow_root_(kDefaultShadowRoot),
skel_source_(kDefaultSkeletonSource),
system_salt_(),
- set_vault_ownership_(true) {
-}
-
-Mount::Mount(const std::string& username, const std::string& entropy_source,
- const std::string& home_dir, const std::string& shadow_root,
- const std::string& skel_source)
- : default_user_(-1),
- default_group_(-1),
- default_username_(username),
- entropy_source_(entropy_source),
- home_dir_(home_dir),
- shadow_root_(shadow_root),
- skel_source_(skel_source),
- system_salt_(),
- set_vault_ownership_(true) {
+ set_vault_ownership_(true),
+ default_crypto_(new Crypto()),
+ crypto_(default_crypto_.get()),
+ default_platform_(new Platform()),
+ platform_(default_platform_.get()) {
}
Mount::~Mount() {
@@ -80,20 +52,16 @@ Mount::~Mount() {
bool Mount::Init() {
bool result = true;
- // Load the passwd entry for the shared user
- struct passwd* user_info = getpwnam(default_username_.c_str());
- if (user_info) {
- // Store the user's uid/gid for later use in changing vault ownership
- default_user_ = user_info->pw_uid;
- default_group_ = user_info->pw_gid;
- } else {
+ // Get the user id and group id of the default user
+ if (!platform_->GetUserId(default_username_, &default_user_,
+ &default_group_)) {
result = false;
}
// One-time load of the global system salt (used in generating username
// hashes)
if (!LoadFileBytes(FilePath(StringPrintf("%s/salt", shadow_root_.c_str())),
- system_salt_)) {
+ &system_salt_)) {
result = false;
}
@@ -126,13 +94,13 @@ bool Mount::EnsureCryptohome(const Credentials& credentials, bool* created) {
bool Mount::MountCryptohome(const Credentials& credentials, int index,
MountError* mount_error) {
- std::string username = credentials.GetFullUsername();
+ std::string username = credentials.GetFullUsernameString();
if (username.compare(kIncognitoUser) == 0) {
- // TODO(fes): Have incognito set error conditions?
+ // TODO(fes): Have guest set error conditions?
if (mount_error) {
*mount_error = MOUNT_ERROR_NONE;
}
- return MountIncognitoCryptohome();
+ return MountGuestCryptohome();
}
bool created = false;
@@ -144,31 +112,18 @@ bool Mount::MountCryptohome(const Credentials& credentials, int index,
return false;
}
- FilePath user_key_file(GetUserKeyFile(credentials, index));
-
- // Retrieve the user's salt for the key index
- SecureBlob user_salt = GetUserSalt(credentials, index);
-
- // Generate the passkey wrapper (key encryption key)
- SecureBlob passkey_wrapper =
- PasskeyToWrapper(credentials.GetPasskey(), user_salt, 1);
-
- // Attempt to unwrap the master key at the index with the passkey wrapper
+ // Attempt to unwrap the vault keyset with the specified credentials
VaultKeyset vault_keyset;
- bool mount_result = UnwrapMasterKey(user_key_file, passkey_wrapper,
- &vault_keyset);
-
- if (!mount_result) {
- if (mount_error) {
- *mount_error = Mount::MOUNT_ERROR_KEY_FAILURE;
- }
+ if (!UnwrapVaultKeyset(credentials, index, &vault_keyset, mount_error)) {
return false;
}
+ crypto_->ClearKeyset();
+
// Add the decrypted key to the keyring so that ecryptfs can use it
string key_signature, fnek_signature;
- if (!AddKeyToEcryptfsKeyring(vault_keyset, &key_signature, &fnek_signature)) {
- LOG(ERROR) << "Cryptohome mount failed because of keyring failure.";
+ if (!crypto_->AddKeyset(vault_keyset, &key_signature, &fnek_signature)) {
+ LOG(INFO) << "Cryptohome mount failed because of keyring failure.";
if (mount_error) {
*mount_error = MOUNT_ERROR_FATAL;
}
@@ -184,12 +139,10 @@ bool Mount::MountCryptohome(const Credentials& credentials, int index,
fnek_signature.c_str(),
key_signature.c_str());
- // TODO(fes): mount(1) -> mount(2): how to issue "user"
+ // Mount cryptohome
string vault_path = GetUserVaultPath(credentials);
- // Attempt to mount the user's cryptohome
- if (mount(vault_path.c_str(), home_dir_.c_str(),
- "ecryptfs", kDefaultMountOptions, ecryptfs_options.c_str())) {
- LOG(ERROR) << "Cryptohome mount failed: " << errno << " for vault: "
+ if (!platform_->Mount(vault_path, home_dir_, "ecryptfs", ecryptfs_options)) {
+ LOG(INFO) << "Cryptohome mount failed: " << errno << " for vault: "
<< vault_path;
if (mount_error) {
*mount_error = MOUNT_ERROR_FATAL;
@@ -210,12 +163,10 @@ bool Mount::MountCryptohome(const Credentials& credentials, int index,
bool Mount::UnmountCryptohome() {
// Try an immediate unmount
bool was_busy;
- if (!Unmount(home_dir_.c_str(), false, &was_busy)) {
- // If the unmount fails, do a lazy unmount
- Unmount(home_dir_.c_str(), true, NULL);
+ if (!platform_->Unmount(home_dir_, false, &was_busy)) {
if (was_busy) {
// Signal processes to close
- if (TerminatePidsWithOpenFiles(home_dir_, false)) {
+ if (platform_->TerminatePidsWithOpenFiles(home_dir_, false)) {
// Then we had to send a SIGINT to some processes with open files. Give
// a "grace" period before killing with a SIGKILL.
// TODO(fes): This isn't ideal, nor is it accurate (a static sleep can't
@@ -223,11 +174,13 @@ bool Mount::UnmountCryptohome() {
// namespace-based mounts, then we can get away from this construct.
PlatformThread::Sleep(100);
sync();
- if (TerminatePidsWithOpenFiles(home_dir_, true)) {
+ if (platform_->TerminatePidsWithOpenFiles(home_dir_, true)) {
PlatformThread::Sleep(100);
}
}
}
+ // Failed to unmount immediately, do a lazy unmount
+ platform_->Unmount(home_dir_, true, NULL);
sync();
// TODO(fes): This should return an error condition if it is still mounted.
// Right now it doesn't, since it should get cleaned up outside of
@@ -238,7 +191,7 @@ bool Mount::UnmountCryptohome() {
//TerminatePidsForUser(default_user_, true);
// Clear the user keyring if the unmount was successful
- keyctl(KEYCTL_CLEAR, KEY_SPEC_USER_KEYRING);
+ crypto_->ClearKeyset();
return true;
}
@@ -251,41 +204,16 @@ bool Mount::RemoveCryptohome(const Credentials& credentials) {
}
bool Mount::IsCryptohomeMounted() {
- // Trivial string match from /etc/mtab to see if the cryptohome mount point is
- // listed. This works because Chrome OS is a controlled environment and the
- // only way /home/chronos/user should be mounted is if cryptohome mounted it.
- string contents;
- if (file_util::ReadFileToString(FilePath(kMtab), &contents)) {
- if (contents.find(StringPrintf(" %s ", home_dir_.c_str()).c_str())
- != string::npos) {
- return true;
- }
- }
- return false;
+ return platform_->IsDirectoryMounted(home_dir_);
}
bool Mount::IsCryptohomeMountedForUser(const Credentials& credentials) {
- // Trivial string match from /etc/mtab to see if the cryptohome mount point
- // and the user's vault path are present. Assumes this user is mounted if it
- // finds both. This will need to change if simultaneous login is implemented.
- string contents;
- if (file_util::ReadFileToString(FilePath(kMtab), &contents)) {
- FilePath vault_path(GetUserVaultPath(credentials));
- if ((contents.find(StringPrintf(" %s ", home_dir_.c_str()).c_str())
- != string::npos)
- && (contents.find(StringPrintf("%s ",
- vault_path.value().c_str()).c_str())
- != string::npos)) {
- return true;
- }
- }
- return false;
+ return platform_->IsDirectoryMountedWith(home_dir_,
+ GetUserVaultPath(credentials));
}
bool Mount::CreateCryptohome(const Credentials& credentials, int index) {
- // Save the current umask
- mode_t original_mask = umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH
- | S_IXOTH);
+ int original_mask = platform_->SetMask(kDefaultUmask);
// Create the user's entry in the shadow root
FilePath user_dir(GetUserDirectory(credentials));
@@ -293,30 +221,29 @@ bool Mount::CreateCryptohome(const Credentials& credentials, int index) {
// Generates a new master key and salt at the given index
if (!CreateMasterKey(credentials, index)) {
- umask(original_mask);
+ platform_->SetMask(original_mask);
return false;
}
// Create the user's path and set the proper ownership
- FilePath vault_path(GetUserVaultPath(credentials));
- if (!file_util::CreateDirectory(vault_path)) {
- LOG(ERROR) << "Couldn't create vault path: " << vault_path.value().c_str();
- umask(original_mask);
+ std::string vault_path = GetUserVaultPath(credentials);
+ if (!file_util::CreateDirectory(FilePath(vault_path))) {
+ LOG(ERROR) << "Couldn't create vault path: " << vault_path.c_str();
+ platform_->SetMask(original_mask);
return false;
}
if (set_vault_ownership_) {
- // TODO(fes): Move platform-specific calls to a separate class
- if (chown(vault_path.value().c_str(), default_user_, default_group_)) {
+ if (!platform_->SetOwnership(vault_path, default_user_, default_group_)) {
LOG(ERROR) << "Couldn't change owner (" << default_user_ << ":"
<< default_group_ << ") of vault path: "
- << vault_path.value().c_str();
- umask(original_mask);
+ << vault_path.c_str();
+ platform_->SetMask(original_mask);
return false;
}
}
// Restore the umask
- umask(original_mask);
+ platform_->SetMask(original_mask);
return true;
}
@@ -324,44 +251,73 @@ bool Mount::TestCredentials(const Credentials& credentials) {
// Iterate over the keys in the user's entry in the shadow root to see if
// these credentials successfully decrypt any
for (int index = 0; /* loop forever */; index++) {
- FilePath user_key_file(GetUserKeyFile(credentials, index));
- if (!file_util::AbsolutePath(&user_key_file)) {
+ MountError mount_error;
+ VaultKeyset vault_keyset;
+ if (UnwrapVaultKeyset(credentials, index, &vault_keyset, &mount_error)) {
+ return true;
+ } else if (mount_error != Mount::MOUNT_ERROR_KEY_FAILURE) {
break;
}
+ }
+ return false;
+}
- SecureBlob user_salt = GetUserSalt(credentials, index);
+bool Mount::UnwrapVaultKeyset(const Credentials& credentials, int index,
+ VaultKeyset* vault_keyset, MountError* error) {
+ // Generate the passkey wrapper (key encryption key)
+ SecureBlob user_salt;
+ GetUserSalt(credentials, index, false, &user_salt);
+ if (user_salt.size() == 0) {
+ if (error) {
+ *error = MOUNT_ERROR_FATAL;
+ }
+ return false;
+ }
+ SecureBlob passkey;
+ credentials.GetPasskey(&passkey);
+ SecureBlob passkey_wrapper;
+ crypto_->PasskeyToWrapper(passkey, user_salt, 1, &passkey_wrapper);
- SecureBlob passkey_wrapper = PasskeyToWrapper(credentials.GetPasskey(),
- user_salt, 1);
+ // Load the encrypted keyset
+ FilePath user_key_file(GetUserKeyFile(credentials, index));
+ if (!file_util::PathExists(user_key_file)) {
+ if (error) {
+ *error = MOUNT_ERROR_NO_SUCH_FILE;
+ }
+ return false;
+ }
+ SecureBlob cipher_text;
+ if (!LoadFileBytes(user_key_file, &cipher_text)) {
+ if (error) {
+ *error = MOUNT_ERROR_FATAL;
+ }
+ return false;
+ }
- VaultKeyset vault_keyset;
- if (UnwrapMasterKey(user_key_file, passkey_wrapper, &vault_keyset)) {
- return true;
+ // Attempt to unwrap the master key at the index with the passkey wrapper
+ if (!crypto_->UnwrapVaultKeyset(cipher_text, passkey_wrapper, vault_keyset)) {
+ if (error) {
+ *error = Mount::MOUNT_ERROR_KEY_FAILURE;
}
+ return false;
}
- return false;
+
+ return true;
}
bool Mount::MigratePasskey(const Credentials& credentials,
const char* old_key) {
// Iterate over the keys in the user's entry in the shadow root to see if
// these credentials successfully decrypt any
- std::string username = credentials.GetFullUsername();
- UsernamePasskey old_credentials(username.c_str(), username.length(),
- old_key, strlen(old_key));
+ std::string username = credentials.GetFullUsernameString();
+ UsernamePasskey old_credentials(username.c_str(),
+ SecureBlob(old_key, strlen(old_key)));
for (int index = 0; /* loop forever */; index++) {
- FilePath user_key_file(GetUserKeyFile(old_credentials, index));
- if (!file_util::AbsolutePath(&user_key_file)) {
- break;
- }
-
- SecureBlob user_salt = GetUserSalt(old_credentials, index);
-
- SecureBlob passkey_wrapper = PasskeyToWrapper(old_credentials.GetPasskey(),
- user_salt, 1);
-
+ // Attempt to unwrap the vault keyset with the specified credentials
+ MountError mount_error;
VaultKeyset vault_keyset;
- if (UnwrapMasterKey(user_key_file, passkey_wrapper, &vault_keyset)) {
+ if (UnwrapVaultKeyset(old_credentials, index, &vault_keyset,
+ &mount_error)) {
// Save to the next key index first so that if there is a failure, we
// don't delete the existing working keyset.
bool save_result = SaveVaultKeyset(credentials, vault_keyset, index + 1);
@@ -396,25 +352,26 @@ bool Mount::MigratePasskey(const Credentials& credentials,
false);
return false;
}
+ } else if (mount_error != Mount::MOUNT_ERROR_KEY_FAILURE) {
+ break;
}
}
return false;
}
-bool Mount::MountIncognitoCryptohome() {
- // Attempt to mount incognitofs
- if (mount("incognitofs", home_dir_.c_str(), "tmpfs",
- kDefaultMountOptions, "")) {
- LOG(ERROR) << "Cryptohome mount failed: " << errno << " for incognitofs";
+bool Mount::MountGuestCryptohome() {
+ // Attempt to mount guestfs
+ if (!platform_->Mount("guestfs", home_dir_, "tmpfs", "")) {
+ LOG(ERROR) << "Cryptohome mount failed: " << errno << " for guestfs";
return false;
}
if (set_vault_ownership_) {
- if (chown(home_dir_.c_str(), default_user_, default_group_)) {
+ if (!platform_->SetOwnership(home_dir_, default_user_, default_group_)) {
LOG(ERROR) << "Couldn't change owner (" << default_user_ << ":"
- << default_group_ << ") of incognitofs path: "
+ << default_group_ << ") of guestfs path: "
<< home_dir_.c_str();
bool was_busy;
- Unmount(home_dir_.c_str(), false, &was_busy);
+ platform_->Unmount(home_dir_.c_str(), false, &was_busy);
return false;
}
}
@@ -495,119 +452,7 @@ void Mount::CopySkeleton() {
}
void Mount::GetSecureRandom(unsigned char *rand, int length) const {
- // TODO(fes): Get assistance from the TPM when it is available
- // Seed the OpenSSL random number generator until it is happy
- while (!RAND_status()) {
- char buffer[256];
- file_util::ReadFile(FilePath(entropy_source_), buffer, sizeof(buffer));
- RAND_add(buffer, sizeof(buffer), sizeof(buffer));
- }
-
- // Have OpenSSL generate the random bytes
- RAND_bytes(rand, length);
-}
-
-bool Mount::Unmount(const std::string& path, bool lazy, bool* was_busy) {
- if (lazy) {
- // TODO(fes): Place platform-specific calls in a separate class so that
- // they can be mocked.
- if (umount2(path.c_str(), MNT_DETACH)) {
- if (was_busy) {
- *was_busy = (errno == EBUSY);
- }
- return false;
- }
- } else {
- if (umount(path.c_str())) {
- if (was_busy) {
- *was_busy = (errno == EBUSY);
- }
- return false;
- }
- }
- if (was_busy) {
- *was_busy = false;
- }
- return true;
-}
-
-bool Mount::UnwrapMasterKey(const FilePath& path,
- const chromeos::Blob& passkey,
- VaultKeyset* vault_keyset) {
- // TODO(fes): Update this with openssl/tpm_engine or opencryptoki once
- // available
- // Load the encrypted master key
- SecureBlob cipher_text;
- if (!LoadFileBytes(path, cipher_text)) {
- LOG(ERROR) << "Unable to read master key file";
- return false;
- }
-
- unsigned int header_size = kOpenSSLMagic.length() + PKCS5_SALT_LEN;
-
- if (cipher_text.size() < header_size) {
- LOG(ERROR) << "Master key file too short";
- return false;
- }
-
- // Grab the salt used in converting the passkey to a key (OpenSSL
- // passkey-encrypted files have the format:
- // Salted__<8-byte-salt><ciphertext>)
- unsigned char salt[PKCS5_SALT_LEN];
- memcpy(salt, &cipher_text[kOpenSSLMagic.length()], PKCS5_SALT_LEN);
-
- cipher_text.erase(cipher_text.begin(), cipher_text.begin() + header_size);
-
- unsigned char wrapper_key[EVP_MAX_KEY_LENGTH];
- unsigned char iv[EVP_MAX_IV_LENGTH];
-
- // Convert the passkey to a key encryption key
- if (!EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, &passkey[0],
- passkey.size(), 1, wrapper_key, iv)) {
- LOG(ERROR) << "Failure converting bytes to key";
- return false;
- }
-
- SecureBlob plain_text(cipher_text.size());
-
- int final_size = 0;
- int decrypt_size = plain_text.size();
-
- // Do the actual decryption
- EVP_CIPHER_CTX d_ctx;
- EVP_CIPHER_CTX_init(&d_ctx);
- EVP_DecryptInit_ex(&d_ctx, EVP_aes_256_ecb(), NULL, wrapper_key, iv);
- if (!EVP_DecryptUpdate(&d_ctx, &plain_text[0], &decrypt_size,
- &cipher_text[0],
- cipher_text.size())) {
- LOG(ERROR) << "DecryptUpdate failed";
- return false;
- }
- if (!EVP_DecryptFinal_ex(&d_ctx, &plain_text[decrypt_size], &final_size)) {
- unsigned long err = ERR_get_error();
- ERR_load_ERR_strings();
- ERR_load_crypto_strings();
-
- LOG(ERROR) << "DecryptFinal Error: " << err
- << ": " << ERR_lib_error_string(err)
- << ", " << ERR_func_error_string(err)
- << ", " << ERR_reason_error_string(err);
-
- return false;
- }
- final_size += decrypt_size;
-
- plain_text.resize(final_size);
-
- if (plain_text.size() != VaultKeyset::SerializedSize()) {
- LOG(ERROR) << "Plain text was not the correct size: " << plain_text.size()
- << ", expected: " << VaultKeyset::SerializedSize();
- return false;
- }
-
- (*vault_keyset).AssignBuffer(plain_text);
-
- return true;
+ crypto_->GetSecureRandom(rand, length);
}
bool Mount::CreateMasterKey(const Credentials& credentials, int index) {
@@ -619,65 +464,29 @@ bool Mount::CreateMasterKey(const Credentials& credentials, int index) {
bool Mount::SaveVaultKeyset(const Credentials& credentials,
const VaultKeyset& vault_keyset,
int index) {
- unsigned char wrapper_key[EVP_MAX_KEY_LENGTH];
- unsigned char iv[EVP_MAX_IV_LENGTH];
- unsigned char salt[PKCS5_SALT_LEN];
-
- // Create a salt for this master key
- GetSecureRandom(salt, sizeof(salt));
- SecureBlob user_salt = GetUserSalt(credentials, index, true);
-
- // Convert the passkey to a passkey wrapper
- SecureBlob passkey_wrapper =
- PasskeyToWrapper(credentials.GetPasskey(), user_salt, 1);
-
- // Convert the passkey wrapper to a key encryption key
- if (!EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, &passkey_wrapper[0],
- passkey_wrapper.size(), 1, wrapper_key, iv)) {
- LOG(ERROR) << "Failure converting bytes to key";
- return false;
- }
-
- SecureBlob keyset_blob = vault_keyset.ToBuffer();
-
- // Store the salt and encrypt the master key
- unsigned int header_size = kOpenSSLMagic.length() + PKCS5_SALT_LEN;
- SecureBlob cipher_text(header_size
- + keyset_blob.size()
- + EVP_CIPHER_block_size(EVP_aes_256_ecb()));
- memcpy(&cipher_text[0], kOpenSSLMagic.c_str(), kOpenSSLMagic.length());
- memcpy(&cipher_text[kOpenSSLMagic.length()], salt, PKCS5_SALT_LEN);
-
- int current_size = header_size;
- int encrypt_size = 0;
- EVP_CIPHER_CTX e_ctx;
- EVP_CIPHER_CTX_init(&e_ctx);
-
- // Encrypt the keyset
- EVP_EncryptInit_ex(&e_ctx, EVP_aes_256_ecb(), NULL, wrapper_key, iv);
- if (!EVP_EncryptUpdate(&e_ctx, &cipher_text[current_size], &encrypt_size,
- &keyset_blob[0],
- keyset_blob.size())) {
- LOG(ERROR) << "EncryptUpdate failed";
- return false;
- }
- current_size += encrypt_size;
- encrypt_size = 0;
-
- // Finish the encryption
- if (!EVP_EncryptFinal_ex(&e_ctx, &cipher_text[current_size], &encrypt_size)) {
- LOG(ERROR) << "EncryptFinal failed";
+ // Get the vault keyset wrapper
+ SecureBlob user_salt;
+ GetUserSalt(credentials, index, true, &user_salt);
+ SecureBlob passkey;
+ credentials.GetPasskey(&passkey);
+ SecureBlob passkey_wrapper;
+ crypto_->PasskeyToWrapper(passkey, user_salt, 1, &passkey_wrapper);
+
+ // Wrap the vault keyset
+ SecureBlob salt(CRYPTOHOME_DEFAULT_KEY_SALT_SIZE);
+ SecureBlob cipher_text;
+ crypto_->GetSecureRandom(static_cast<unsigned char*>(salt.data()),
+ salt.size());
+ if (!crypto_->WrapVaultKeyset(vault_keyset, passkey_wrapper, salt,
+ &cipher_text)) {
+ LOG(ERROR) << "Wrapping vault keyset failed";
return false;
}
- current_size += encrypt_size;
- cipher_text.resize(current_size);
-
- chromeos::SecureMemset(wrapper_key, sizeof(wrapper_key), 0);
// Save the master key
unsigned int data_written = file_util::WriteFile(
FilePath(GetUserKeyFile(credentials, index)),
- reinterpret_cast<const char*>(&cipher_text[0]),
+ static_cast<const char*>(cipher_text.const_data()),
cipher_text.size());
if (data_written != cipher_text.size()) {
@@ -687,145 +496,21 @@ bool Mount::SaveVaultKeyset(const Credentials& credentials,
return true;
}
-SecureBlob Mount::PasskeyToWrapper(const chromeos::Blob& passkey,
- const chromeos::Blob& salt, int iters) {
- // TODO(fes): Update this when TPM support is available, or use a memory-
- // bound strengthening algorithm.
- int update_length = passkey.size();
- SecureBlob holder(CRYPTOHOME_MAX(update_length, SHA_DIGEST_LENGTH));
- memcpy(&holder[0], &passkey[0], update_length);
-
- // Repeatedly hash the user passkey and salt to generate the wrapper
- for (int i = 0; i < iters; ++i) {
- SHA_CTX ctx;
- unsigned char md_value[SHA_DIGEST_LENGTH];
-
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, &salt[0], salt.size());
- SHA1_Update(&ctx, &holder[0], update_length);
- SHA1_Final(md_value, &ctx);
-
- memcpy(&holder[0], md_value, SHA_DIGEST_LENGTH);
- update_length = SHA_DIGEST_LENGTH;
- }
-
- holder.resize(update_length);
- SecureBlob wrapper(update_length * 2);
- AsciiEncodeToBuffer(holder, reinterpret_cast<char*>(&wrapper[0]),
- wrapper.size());
- return wrapper;
-}
-
-SecureBlob Mount::GetSystemSalt() {
- return system_salt_;
+void Mount::GetSystemSalt(chromeos::Blob* salt) {
+ *salt = system_salt_;
}
-SecureBlob Mount::GetUserSalt(const Credentials& credentials, int index,
- bool force) {
+void Mount::GetUserSalt(const Credentials& credentials, int index, bool force,
+ SecureBlob* salt) {
FilePath path(GetUserSaltFile(credentials, index));
- return GetOrCreateSalt(path, CRYPTOHOME_DEFAULT_SALT_LENGTH, force);
-}
-
-SecureBlob Mount::GetOrCreateSalt(const FilePath& path, int length,
- bool force) {
- SecureBlob salt;
- if (force || !file_util::PathExists(path)) {
- // If this salt doesn't exist, automatically create it
- salt.resize(length);
- GetSecureRandom(&salt[0], salt.size());
- int data_written = file_util::WriteFile(path,
- reinterpret_cast<const char*>(&salt[0]),
- length);
- if (data_written != length) {
- LOG(ERROR) << "Could not write user salt";
- return SecureBlob();
- }
- } else {
- // Otherwise just load the contents of the salt
- int64 file_size;
- if (!file_util::GetFileSize(path, &file_size)) {
- LOG(ERROR) << "Could not get size of " << path.value();
- return SecureBlob();
- }
- if (file_size > INT_MAX) {
- LOG(ERROR) << "File " << path.value() << " is too large: " << file_size;
- return SecureBlob();
- }
- salt.resize(file_size);
- int data_read = file_util::ReadFile(path, reinterpret_cast<char*>(&salt[0]),
- file_size);
- if (data_read != file_size) {
- LOG(ERROR) << "Could not read entire file " << file_size;
- return SecureBlob();
- }
- }
- return salt;
-}
-
-void Mount::AsciiEncodeToBuffer(const chromeos::Blob& blob, char* buffer,
- int buffer_length) {
- const char hex_chars[] = "0123456789abcdef";
- int i = 0;
- for (chromeos::Blob::const_iterator it = blob.begin();
- it < blob.end() && (i + 1) < buffer_length; ++it) {
- buffer[i++] = hex_chars[((*it) >> 4) & 0x0f];
- buffer[i++] = hex_chars[(*it) & 0x0f];
- }
- if (i < buffer_length) {
- buffer[i] = '\0';
- }
-}
-
-bool Mount::AddKeyToEcryptfsKeyring(const VaultKeyset& vault_keyset,
- string* key_signature,
- string* fnek_signature) {
- // Clear the user keyring
- keyctl(KEYCTL_CLEAR, KEY_SPEC_USER_KEYRING);
-
- // Add the FEK
- *key_signature = chromeos::AsciiEncode(vault_keyset.FEK_SIG());
- if (!PushVaultKey(vault_keyset.FEK(), *key_signature,
- vault_keyset.FEK_SALT())) {
- LOG(ERROR) << "Couldn't add ecryptfs key to keyring";
- return false;
- }
-
- // Add the FNEK
- *fnek_signature = chromeos::AsciiEncode(vault_keyset.FNEK_SIG());
- if (!PushVaultKey(vault_keyset.FNEK(), *fnek_signature,
- vault_keyset.FNEK_SALT())) {
- LOG(ERROR) << "Couldn't add ecryptfs fnek key to keyring";
- return false;
- }
-
- return true;
-}
-
-bool Mount::PushVaultKey(const SecureBlob& key, const std::string& key_sig,
- const SecureBlob& salt) {
- DCHECK(key.size() == ECRYPTFS_MAX_KEY_BYTES);
- DCHECK(key_sig.length() == (ECRYPTFS_SIG_SIZE * 2));
- DCHECK(salt.size() == ECRYPTFS_SALT_SIZE);
-
- struct ecryptfs_auth_tok auth_token;
-
- generate_payload(&auth_token, const_cast<char*>(key_sig.c_str()),
- const_cast<char*>(reinterpret_cast<const char*>(&salt[0])),
- const_cast<char*>(reinterpret_cast<const char*>(&key[0])));
-
- if (ecryptfs_add_auth_tok_to_keyring(&auth_token,
- const_cast<char*>(key_sig.c_str())) < 0) {
- LOG(ERROR) << "PushVaultKey failed";
- }
-
- return true;
+ crypto_->GetOrCreateSalt(path, CRYPTOHOME_DEFAULT_SALT_LENGTH, force, salt);
}
bool Mount::LoadFileBytes(const FilePath& path,
- SecureBlob& blob) {
+ SecureBlob* blob) {
int64 file_size;
if (!file_util::PathExists(path)) {
- LOG(ERROR) << path.value() << " does not exist!";
+ LOG(INFO) << path.value() << " does not exist!";
return false;
}
if (!file_util::GetFileSize(path, &file_size)) {
@@ -844,155 +529,8 @@ bool Mount::LoadFileBytes(const FilePath& path,
LOG(ERROR) << "Could not read entire file " << file_size;
return false;
}
- blob.swap(buf);
+ blob->swap(buf);
return true;
}
-bool Mount::TerminatePidsWithOpenFiles(const std::string& path, bool hard) {
- std::vector<pid_t> pids = LookForOpenFiles(path);
- for (std::vector<pid_t>::iterator it = pids.begin(); it != pids.end(); it++) {
- pid_t pid = static_cast<pid_t>(*it);
- if (pid != getpid()) {
- if (hard) {
- kill(pid, SIGTERM);
- } else {
- kill(pid, SIGKILL);
- }
- }
- }
- return (pids.size() != 0);
-}
-
-std::vector<pid_t> Mount::LookForOpenFiles(const std::string& path_in) {
- // Make sure that if we get a directory, it has a trailing separator
- FilePath file_path(path_in);
- file_util::EnsureEndsWithSeparator(&file_path);
- std::string path = file_path.value();
-
- std::vector<pid_t> pids;
-
- // Open /proc
- DIR* proc_dir = opendir(kProcDir.c_str());
-
- if (!proc_dir) {
- return pids;
- }
-
- int linkbuf_length = path.length();
- std::vector<char> linkbuf(linkbuf_length);
-
- // List PIDs in /proc
- while (struct dirent* pid_dirent = readdir(proc_dir)) {
- pid_t pid = static_cast<pid_t>(atoi(pid_dirent->d_name));
- // Ignore PID 1 and errors
- if (pid <= 1) {
- continue;
- }
- // Open /proc/<pid>/fd
- std::string fd_dirname = StringPrintf("%s/%d/fd", kProcDir.c_str(), pid);
- DIR* fd_dir = opendir(fd_dirname.c_str());
- if (!fd_dir) {
- continue;
- }
-
- // List open file descriptors
- while (struct dirent* fd_dirent = readdir(fd_dir)) {
- std::string fd_path = StringPrintf("%s/%s", fd_dirname.c_str(),
- fd_dirent->d_name);
- ssize_t link_length = readlink(fd_path.c_str(), &linkbuf[0],
- linkbuf.size());
- if (link_length > 0) {
- std::string open_file(&linkbuf[0], link_length);
- if (open_file.length() >= path.length()) {
- if (open_file.substr(0, path.length()).compare(path) == 0) {
- pids.push_back(pid);
- break;
- }
- }
- }
- }
-
- closedir(fd_dir);
- }
-
- closedir(proc_dir);
-
- return pids;
-}
-
-bool Mount::TerminatePidsForUser(const uid_t uid, bool hard) {
- std::vector<pid_t> pids = GetPidsForUser(uid);
- for (std::vector<pid_t>::iterator it = pids.begin(); it != pids.end(); it++) {
- pid_t pid = static_cast<pid_t>(*it);
- if (pid != getpid()) {
- if (hard) {
- kill(pid, SIGTERM);
- } else {
- kill(pid, SIGKILL);
- }
- }
- }
- return (pids.size() != 0);
-}
-
-// TODO(fes): Pull this into a separate helper class
-std::vector<pid_t> Mount::GetPidsForUser(uid_t uid) {
- std::vector<pid_t> pids;
-
- // Open /proc
- DIR* proc_dir = opendir(kProcDir.c_str());
-
- if (!proc_dir) {
- return pids;
- }
-
- // List PIDs in /proc
- while (struct dirent* pid_dirent = readdir(proc_dir)) {
- pid_t pid = static_cast<pid_t>(atoi(pid_dirent->d_name));
- if (pid <= 0) {
- continue;
- }
- // Open /proc/<pid>/status
- std::string stat_path = StringPrintf("%s/%d/status", kProcDir.c_str(),
- pid);
- string contents;
- if (!file_util::ReadFileToString(FilePath(stat_path), &contents)) {
- continue;
- }
-
- size_t uid_loc = contents.find("Uid:");
- if (!uid_loc) {
- continue;
- }
- uid_loc += 4;
-
- size_t uid_end = contents.find("\n", uid_loc);
- if (!uid_end) {
- continue;
- }
-
- contents = contents.substr(uid_loc, uid_end - uid_loc);
-
- std::vector<std::string> tokens;
- Tokenize(contents, " \t", &tokens);
-
- for (std::vector<std::string>::iterator it = tokens.begin();
- it != tokens.end(); it++) {
- std::string& value = *it;
- if (value.length() == 0) {
- continue;
- }
- uid_t check_uid = static_cast<uid_t>(atoi(value.c_str()));
- if (check_uid == uid) {
- pids.push_back(pid);
- break;
- }
- }
- }
-
- closedir(proc_dir);
-
- return pids;
-}
-
-} // cryptohome
+} // namespace cryptohome
« no previous file with comments | « mount.h ('k') | mount_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698