summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorgspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 18:49:54 +0000
committergspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 18:49:54 +0000
commitc64b9143b18ce8ec3746c1288c7c1204e8ce6612 (patch)
treeffb0482fb7be708006274e1a3e3d0a29e7030b13 /crypto
parent18a8ff16490804f05c5f3d939e863c3b09749ede (diff)
downloadchromium_src-c64b9143b18ce8ec3746c1288c7c1204e8ce6612.zip
chromium_src-c64b9143b18ce8ec3746c1288c7c1204e8ce6612.tar.gz
chromium_src-c64b9143b18ce8ec3746c1288c7c1204e8ce6612.tar.bz2
This adds calls to new API for cryptohomed that gives status
of the PKCS#11 initialization of the TPM. Also, add cros_library wrapper calls for new libcros API. BUG=chromium-os:12303 TEST=Ran on device, checked to make sure TPM certs showed up, indicating that status and user PIN were successfully retrieved. Review URL: http://codereview.chromium.org/6838032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82134 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'crypto')
-rw-r--r--crypto/nss_util.cc164
-rw-r--r--crypto/nss_util.h37
-rw-r--r--crypto/rsa_private_key_nss.cc7
3 files changed, 122 insertions, 86 deletions
diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc
index 198a692..d4f0855 100644
--- a/crypto/nss_util.cc
+++ b/crypto/nss_util.cc
@@ -51,13 +51,6 @@ const char kNSSDatabaseName[] = "Real NSS database";
const char kOpencryptokiModuleName[] = "opencryptoki";
const char kOpencryptokiPath[] = "/usr/lib/opencryptoki/libopencryptoki.so";
-// TODO(gspencer): Get these values from cryptohomed's dbus API when
-// we ask if it has initialized the TPM yet. These should not be
-// hard-coded here.
-const char kTPMTokenName[] = "Initialized by CrOS";
-const char kTPMUserPIN[] = "111111";
-const char kTPMSecurityOfficerPIN[] = "000000";
-
// Fake certificate authority database used for testing.
static const FilePath::CharType kReadOnlyCertDB[] =
FILE_PATH_LITERAL("/etc/fake_root_ca/nssdb");
@@ -109,9 +102,15 @@ FilePath GetInitialConfigDirectory() {
char* PKCS11PasswordFunc(PK11SlotInfo* slot, PRBool retry, void* arg) {
#if defined(OS_CHROMEOS)
// If we get asked for a password for the TPM, then return the
- // static password we use.
- if (PK11_GetTokenName(slot) == crypto::GetTPMTokenName())
- return PORT_Strdup(GetTPMUserPIN().c_str());
+ // well known password we use, as long as the TPM slot has been
+ // initialized.
+ if (crypto::IsTPMTokenReady()) {
+ std::string token_name;
+ std::string user_pin;
+ crypto::GetTPMTokenInfo(&token_name, &user_pin);
+ if (PK11_GetTokenName(slot) == token_name)
+ return PORT_Strdup(user_pin.c_str());
+ }
#endif
crypto::CryptoModuleBlockingPasswordDelegate* delegate =
reinterpret_cast<crypto::CryptoModuleBlockingPasswordDelegate*>(arg);
@@ -237,51 +236,26 @@ class NSSInitSingleton {
}
}
- bool EnableTPMForNSS() {
- if (!opencryptoki_module_) {
- // This loads the opencryptoki module so we can talk to the
- // hardware TPM.
- opencryptoki_module_ = LoadModule(
- kOpencryptokiModuleName,
- kOpencryptokiPath,
- // trustOrder=100 -- means it'll select this as the most
- // trusted slot for the mechanisms it provides.
- // slotParams=... -- selects RSA as the only mechanism, and only
- // asks for the password when necessary (instead of every
- // time, or after a timeout).
- "trustOrder=100 slotParams=(1={slotFlags=[RSA] askpw=only})");
- if (opencryptoki_module_) {
- // We shouldn't need to initialize the TPM PIN here because
- // it'll be taken care of by cryptohomed, but we have to make
- // sure that it is initialized.
-
- // TODO(gspencer): replace this with a dbus call that will
- // check to see that cryptohomed has initialized the PINs, and
- // will fetch the token name and PINs for accessing the TPM.
- EnsureTPMInit();
-
- // If this is set, then we'll use the TPM by default.
- tpm_slot_ = GetTPMSlot();
- return true;
- }
- }
- return false;
+ void EnableTPMTokenForNSS(TPMTokenInfoDelegate* info_delegate) {
+ CHECK(info_delegate);
+ tpm_token_info_delegate_.reset(info_delegate);
+ // Try to load once to avoid jank later. Ignore the return value,
+ // because if it fails we will try again later.
+ EnsureTPMTokenReady();
}
- std::string GetTPMTokenName() {
- // TODO(gspencer): This should come from the dbus interchange with
- // cryptohomed instead of being hard-coded.
- return std::string(kTPMTokenName);
+ void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) {
+ tpm_token_info_delegate_->GetTokenInfo(token_name, user_pin);
}
- std::string GetTPMUserPIN() {
- // TODO(gspencer): This should come from the dbus interchange with
- // cryptohomed instead of being hard-coded.
- return std::string(kTPMUserPIN);
+ bool IsTPMTokenReady() {
+ return tpm_slot_ != NULL;
}
PK11SlotInfo* GetTPMSlot() {
- return FindSlotWithTokenName(GetTPMTokenName());
+ std::string token_name;
+ GetTPMTokenInfo(&token_name, NULL);
+ return FindSlotWithTokenName(token_name);
}
#endif // defined(OS_CHROMEOS)
@@ -312,10 +286,22 @@ class NSSInitSingleton {
PK11SlotInfo* GetPrivateNSSKeySlot() {
if (test_slot_)
return PK11_ReferenceSlot(test_slot_);
- // If the TPM slot has been opened, then return that one.
- if (tpm_slot_)
- return PK11_ReferenceSlot(tpm_slot_);
- // If it hasn't, then return the software slot.
+
+#if defined(OS_CHROMEOS)
+ // Make sure that if EnableTPMTokenForNSS has been called that we
+ // have successfully loaded opencryptoki.
+ if (tpm_token_info_delegate_.get() != NULL) {
+ if (EnsureTPMTokenReady()) {
+ return PK11_ReferenceSlot(tpm_slot_);
+ } else {
+ // If we were supposed to get the hardware token, but were
+ // unable to, return NULL rather than fall back to sofware.
+ return NULL;
+ }
+ }
+#endif
+ // If we weren't supposed to enable the TPM for NSS, then return
+ // the software slot.
if (software_slot_)
return PK11_ReferenceSlot(software_slot_);
return PK11_GetInternalKeySlot();
@@ -502,21 +488,6 @@ class NSSInitSingleton {
}
#endif
-#if defined(OS_CHROMEOS)
- void EnsureTPMInit() {
- crypto::ScopedPK11Slot tpm_slot(GetTPMSlot());
- if (tpm_slot.get()) {
- // TODO(gspencer): Remove this in favor of the dbus API for
- // cryptohomed when that is available.
- if (PK11_NeedUserInit(tpm_slot.get())) {
- PK11_InitPin(tpm_slot.get(),
- kTPMSecurityOfficerPIN,
- kTPMUserPIN);
- }
- }
- }
-#endif
-
static PK11SlotInfo* OpenUserDB(const FilePath& path,
const char* description) {
const std::string modspec =
@@ -534,9 +505,52 @@ class NSSInitSingleton {
return db_slot;
}
+#if defined(OS_CHROMEOS)
+ // This is called whenever we want to make sure opencryptoki is
+ // properly loaded, because it can fail shortly after the initial
+ // login while the PINs are being initialized, and we want to retry
+ // if this happens.
+ bool EnsureTPMTokenReady() {
+ // If EnableTPMTokenForNSS hasn't been called, or if everything is
+ // already initialized, then this call succeeds.
+ if (tpm_token_info_delegate_.get() == NULL ||
+ (opencryptoki_module_ && tpm_slot_)) {
+ return true;
+ }
+
+ if (tpm_token_info_delegate_->IsTokenReady()) {
+ // This tries to load the opencryptoki module so NSS can talk to
+ // the hardware TPM.
+ if (!opencryptoki_module_) {
+ opencryptoki_module_ = LoadModule(
+ kOpencryptokiModuleName,
+ kOpencryptokiPath,
+ // trustOrder=100 -- means it'll select this as the most
+ // trusted slot for the mechanisms it provides.
+ // slotParams=... -- selects RSA as the only mechanism, and only
+ // asks for the password when necessary (instead of every
+ // time, or after a timeout).
+ "trustOrder=100 slotParams=(1={slotFlags=[RSA] askpw=only})");
+ }
+ if (opencryptoki_module_) {
+ // If this gets set, then we'll use the TPM for certs with
+ // private keys, otherwise we'll fall back to the software
+ // implementation.
+ tpm_slot_ = GetTPMSlot();
+ return tpm_slot_ != NULL;
+ }
+ }
+ return false;
+ }
+#endif
+
// If this is set to true NSS is forced to be initialized without a DB.
static bool force_nodb_init_;
+#if defined(OS_CHROMEOS)
+ scoped_ptr<TPMTokenInfoDelegate> tpm_token_info_delegate_;
+#endif
+
SECMODModule* opencryptoki_module_;
PK11SlotInfo* software_slot_;
PK11SlotInfo* test_slot_;
@@ -663,17 +677,21 @@ void OpenPersistentNSSDB() {
g_nss_singleton.Get().OpenPersistentNSSDB();
}
-bool EnableTPMForNSS() {
- return g_nss_singleton.Get().EnableTPMForNSS();
+TPMTokenInfoDelegate::TPMTokenInfoDelegate() {}
+TPMTokenInfoDelegate::~TPMTokenInfoDelegate() {}
+
+void EnableTPMTokenForNSS(TPMTokenInfoDelegate* info_delegate) {
+ g_nss_singleton.Get().EnableTPMTokenForNSS(info_delegate);
}
-std::string GetTPMTokenName() {
- return g_nss_singleton.Get().GetTPMTokenName();
+void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) {
+ g_nss_singleton.Get().GetTPMTokenInfo(token_name, user_pin);
}
-std::string GetTPMUserPIN() {
- return g_nss_singleton.Get().GetTPMUserPIN();
+bool IsTPMTokenReady() {
+ return g_nss_singleton.Get().IsTPMTokenReady();
}
+
#endif // defined(OS_CHROMEOS)
// TODO(port): Implement this more simply. We can convert by subtracting an
diff --git a/crypto/nss_util.h b/crypto/nss_util.h
index 6cb03a8..3ed79fe 100644
--- a/crypto/nss_util.h
+++ b/crypto/nss_util.h
@@ -86,17 +86,34 @@ bool CheckNSSVersion(const char* version);
// GetPublicNSSKeySlot().
void OpenPersistentNSSDB();
-// Load the opencryptoki library into NSS so that we can access the
-// TPM through NSS. Once this is called, GetPrivateNSSKeySlot() will
-// return the TPM slot if one was found. Returns false if it was
-// unable to load opencryptoki or open the TPM slot.
-bool EnableTPMForNSS();
-
-// Get name for the built-in TPM token on ChromeOS.
-std::string GetTPMTokenName();
+// A delegate class that we can use it to access the cros API for
+// communication with cryptohomed and the TPM.
+class TPMTokenInfoDelegate {
+ public:
+ TPMTokenInfoDelegate();
+ virtual ~TPMTokenInfoDelegate();
+ virtual bool IsTokenReady() const = 0;
+ virtual void GetTokenInfo(std::string* token_name,
+ std::string* user_pin) const = 0;
+};
-// Get the user PIN for the built-in TPM token on ChromeOS.
-std::string GetTPMUserPIN();
+// Indicates that NSS should load the opencryptoki library so that we
+// can access the TPM through NSS. Once this is called,
+// GetPrivateNSSKeySlot() will return the TPM slot if one was found.
+// Takes ownership of the passed-in delegate object so it can access
+// the cros library to talk to cryptohomed.
+void EnableTPMTokenForNSS(TPMTokenInfoDelegate* delegate);
+
+// Get name and user PIN for the built-in TPM token on ChromeOS.
+// Either one can safely be NULL. Should only be called after
+// EnableTPMTokenForNSS has been called with a non-null delegate.
+void GetTPMTokenInfo(std::string* token_name, std::string* user_pin);
+
+// Returns true if the TPM is owned and PKCS#11 initialized with the
+// user and security officer PINs, and has been enabled in NSS by
+// calling EnableTPMForNSS, and opencryptoki has been successfully
+// loaded into NSS.
+bool IsTPMTokenReady();
#endif
// Convert a NSS PRTime value into a base::Time object.
diff --git a/crypto/rsa_private_key_nss.cc b/crypto/rsa_private_key_nss.cc
index f5d4222..bac7281 100644
--- a/crypto/rsa_private_key_nss.cc
+++ b/crypto/rsa_private_key_nss.cc
@@ -75,7 +75,7 @@ RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
const std::vector<uint8>& input) {
return CreateFromPrivateKeyInfoWithParams(input,
PR_TRUE /* permanent */,
- PR_TRUE /* seneitive */);
+ PR_TRUE /* sensitive */);
}
// static
@@ -105,8 +105,9 @@ RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
return NULL;
}
- // Now, look for the associated private key in the user's NSS DB. If it's
- // not there, consider that an error.
+ // Now, look for the associated private key in the user's
+ // hardware-backed NSS DB. If it's not there, consider that an
+ // error.
PK11SlotInfo *slot = GetPrivateNSSKeySlot();
if (!slot) {
NOTREACHED();