Index: service.cc |
diff --git a/service.cc b/service.cc |
index ed47224568e5c6a38f6111187bcefbf06fd759ed..09c6630a08444317e2ae43a1113f775b360c6f9f 100644 |
--- a/service.cc |
+++ b/service.cc |
@@ -12,11 +12,14 @@ |
#include <base/string_util.h> |
#include <base/time.h> |
#include <chromeos/dbus/dbus.h> |
+#include <string> |
+#include <vector> |
#include "cryptohome/marshal.glibmarshal.h" |
#include "cryptohome_event_source.h" |
#include "interface.h" |
#include "crypto.h" |
+#include "lockbox.h" |
#include "mount.h" |
#include "secure_blob.h" |
#include "tpm.h" |
@@ -86,7 +89,9 @@ Service::Service() |
async_complete_signal_(-1), |
tpm_init_signal_(-1), |
event_source_(), |
- auto_cleanup_period_(kAutoCleanupPeriodMS) { |
+ auto_cleanup_period_(kAutoCleanupPeriodMS), |
+ default_lockbox_(new cryptohome::Lockbox()), |
+ lockbox_(default_lockbox_.get()) { |
} |
Service::~Service() { |
@@ -103,15 +108,19 @@ bool Service::Initialize() { |
bool result = true; |
mount_->Init(); |
+ // If the TPM is unowned or doesn't exist, it's safe for |
+ // this function to be called again. However, it shouldn't |
+ // be called across multiple threads in parallel. |
gauravsh
2011/04/11 04:03:20
Is this comment for InitializeLockBox()? If so, ca
Will Drewry
2011/04/13 16:04:59
The part that is relevant (thread safety) is in th
|
+ InitializeLockbox(); |
+ |
Tpm* tpm = const_cast<Tpm*>(mount_->get_crypto()->get_tpm()); |
- if (tpm && initialize_tpm_) { |
+ if (tpm && initialize_tpm_) { |
tpm_init_->set_tpm(tpm); |
tpm_init_->Init(this); |
if (!SeedUrandom()) { |
LOG(ERROR) << "FAILED TO SEED /dev/urandom AT START"; |
} |
} |
- |
// Install the type-info for the service with dbus. |
dbus_g_object_type_install_info(gobject::cryptohome_get_type(), |
&gobject::dbus_glib_cryptohome_object_info); |
@@ -156,6 +165,17 @@ bool Service::Initialize() { |
return result; |
} |
+void Service::InitializeLockbox() { |
gauravsh
2011/04/11 04:03:20
Should this return true or false? Otherwise the ca
Will Drewry
2011/04/13 16:04:59
The caller doesn't matter as much unless we want c
|
+ Tpm* tpm = const_cast<Tpm*>(mount_->get_crypto()->get_tpm()); |
+ // Don't call this until the TPM is owned. |
+ if (tpm && !tpm->IsOwned()) |
+ return; |
+ // tpm will be NULL if the system lacks one. |
+ lockbox_->Init(tpm, |
+ Lockbox::kDefaultNvramIndex, |
+ Lockbox::kDefaultPath); |
+} |
+ |
bool Service::SeedUrandom() { |
SecureBlob random; |
if (!tpm_init_->GetRandomData(kDefaultRandomSeedLength, &random)) { |
@@ -206,6 +226,7 @@ void Service::NotifyEvent(CryptohomeEventBase* event) { |
TpmInitStatus* result = static_cast<TpmInitStatus*>(event); |
g_signal_emit(cryptohome_, tpm_init_signal_, 0, tpm_init_->IsTpmReady(), |
tpm_init_->IsTpmEnabled(), result->get_took_ownership()); |
+ // TODO(wad) should we package up a Lockbox status here too? |
} |
} |
@@ -219,6 +240,9 @@ void Service::InitializeTpmComplete(bool status, bool took_ownership) { |
mount_task->set_complete_event(&event); |
mount_thread_.message_loop()->PostTask(FROM_HERE, mount_task); |
event.Wait(); |
+ // Initialize the install-time locked attributes since we |
+ // can't do it prior to ownership. |
+ InitializeLockbox(); |
} |
// The event source will free this object |
TpmInitStatus* tpm_init_status = new TpmInitStatus(); |
@@ -567,6 +591,68 @@ gboolean Service::TpmClearStoredPassword(GError** error) { |
return TRUE; |
} |
+gboolean Service::LockboxGet(gchar* name, |
+ GArray** OUT_value, |
+ gboolean* OUT_successful, |
+ GError** error) { |
+ chromeos::Blob value; |
+ *OUT_successful = lockbox_->Get(name, &value); |
+ *OUT_value = g_array_new(false, false, sizeof(char)); |
+ if (*OUT_successful) |
+ g_array_append_vals(*OUT_value, &value.front(), value.size()); |
+ return TRUE; |
+} |
+ |
+gboolean Service::LockboxSet(gchar* name, |
+ GArray* value, |
+ gboolean* OUT_successful, |
+ GError** error) { |
+ // Convert from GArray to vector |
+ chromeos::Blob value_blob; |
+ value_blob.assign(value->data, value->data + value->len); |
+ *OUT_successful = lockbox_->Set(name, value_blob); |
+ return TRUE; |
+} |
+ |
+gboolean Service::LockboxLock(gboolean* OUT_locked, GError** error) { |
+ *OUT_locked = lockbox_->Lock(); |
+ return TRUE; |
+} |
+ |
+gboolean Service::LockboxCount(gint* OUT_count, GError** error) { |
+ // TODO(wad) for all of these functions return error on uninit. |
+ // Follow the CHROMEOS_LOGIN_ERROR quark example in chromeos/dbus/ |
+ *OUT_count = lockbox_->Count(); |
+ return TRUE; |
+} |
+ |
+gboolean Service::LockboxIsReady(gboolean* OUT_ready, GError** error) { |
+ // Initialization is handled automatically when possible and async |
+ // notification implies readiness. This allows other code to poll. |
+ *OUT_ready = (lockbox_->initialized() == true); |
+ return TRUE; |
+} |
+ |
+gboolean Service::LockboxIsLocked(gboolean* OUT_locked, GError** error) { |
+ *OUT_locked = (lockbox_->locked() == true); |
+ return TRUE; |
+} |
+ |
+gboolean Service::LockboxIsSecure(gboolean* OUT_secure, GError** error) { |
+ *OUT_secure = (lockbox_->secure() == true); |
+ return TRUE; |
+} |
+ |
+gboolean Service::LockboxIsTampered(gboolean* OUT_tampered, GError** error) { |
+ *OUT_tampered = (lockbox_->tampered() == true); |
+ return TRUE; |
+} |
+ |
+gboolean Service::LockboxIsLegacy(gboolean* OUT_legacy, GError** error) { |
+ *OUT_legacy = (lockbox_->legacy() == true); |
+ return TRUE; |
+} |
+ |
gboolean Service::GetStatusString(gchar** OUT_status, GError** error) { |
Tpm::TpmStatusInfo tpm_status; |
mount_->get_crypto()->EnsureTpm(false); |
@@ -627,6 +713,26 @@ gboolean Service::GetStatusString(gchar** OUT_status, GError** error) { |
} while(false); |
} |
+ int lockbox_size = lockbox_->Count(); |
+ std::string lockbox_data("Lockbox Contents:\n"); |
+ if (lockbox_->Count()) { |
+ std::string name; |
+ chromeos::Blob value; |
+ for (int pair = 0; pair < lockbox_size; ++pair) { |
+ lockbox_data += StringPrintf( |
gauravsh
2011/04/11 04:03:20
is using += as efficient as using append()? (not t
Will Drewry
2011/04/13 16:04:59
No idea. Done.
gauravsh
2011/04/14 07:39:52
Yeah, it seems either append or += is ok. What's n
|
+ " Index...........................: %d\n", pair); |
+ if (lockbox_->GetNameByIndex(pair, &name) && |
+ lockbox_->GetValueByIndex(pair, &value)) { |
+ std::string value_str(reinterpret_cast<const char*>(&value[0]), |
+ value.size()); |
+ lockbox_data += StringPrintf( |
+ " Name............................: %s\n" |
+ " Value...........................: %s\n", |
+ name.c_str(), |
+ value_str.c_str()); |
+ } |
+ } |
+ } |
*OUT_status = g_strdup_printf( |
"TPM Status:\n" |
@@ -644,7 +750,15 @@ gboolean Service::GetStatusString(gchar** OUT_status, GError** error) { |
" Last Error......................: %08x\n" |
"%s" |
"Mount Status:\n" |
- " Vault Is Mounted................: %s\n", |
+ " Vault Is Mounted................: %s\n" |
+ "Lockbox Status:\n" |
+ " Initialized.....................: %s\n" |
+ " Secure..........................: %s\n" |
+ " Legacy..........................: %s\n" |
+ " Locked..........................: %s\n" |
+ " Tampered........................: %s\n" |
+ " Entries.........................: %d\n" |
+ "%s", |
(tpm_status.Enabled ? "1" : "0"), |
(tpm_status.Owned ? "1" : "0"), |
(tpm_status.BeingOwned ? "1" : "0"), |
@@ -658,7 +772,14 @@ gboolean Service::GetStatusString(gchar** OUT_status, GError** error) { |
(tpm_status.ThisInstanceHasKeyHandle ? "1" : "0"), |
tpm_status.LastTpmError, |
user_data.c_str(), |
- (mount_->IsCryptohomeMounted() ? "1" : "0")); |
+ (mount_->IsCryptohomeMounted() ? "1" : "0"), |
+ (lockbox_->initialized() ? "1" : "0"), |
+ (lockbox_->secure() ? "1" : "0"), |
+ (lockbox_->legacy() ? "1" : "0"), |
+ (lockbox_->locked() ? "1" : "0"), |
+ (lockbox_->tampered() ? "1" : "0"), |
+ lockbox_size, |
+ lockbox_data.c_str()); |
return TRUE; |
} |