зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1842303 - remove some unused nsIOSKeyStore functions r=nkulatova
Differential Revision: https://phabricator.services.mozilla.com/D183054
This commit is contained in:
Родитель
3efc235517
Коммит
f149487bb4
|
@ -39,17 +39,6 @@ CredentialManagerSecret::CredentialManagerSecret() {}
|
|||
|
||||
CredentialManagerSecret::~CredentialManagerSecret() {}
|
||||
|
||||
nsresult CredentialManagerSecret::Lock() {
|
||||
// The Windows credential manager can't be locked.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult CredentialManagerSecret::Unlock() {
|
||||
// The Windows credential manager is always unlocked when the user is logged
|
||||
// in.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult CredentialManagerSecret::StoreSecret(const nsACString& aSecret,
|
||||
const nsACString& aLabel) {
|
||||
if (aSecret.Length() > CRED_MAX_CREDENTIAL_BLOB_SIZE) {
|
||||
|
|
|
@ -19,8 +19,6 @@ class CredentialManagerSecret final : public AbstractOSKeyStore {
|
|||
virtual nsresult StoreSecret(const nsACString& secret,
|
||||
const nsACString& label) override;
|
||||
virtual nsresult DeleteSecret(const nsACString& label) override;
|
||||
virtual nsresult Lock() override;
|
||||
virtual nsresult Unlock() override;
|
||||
|
||||
virtual ~CredentialManagerSecret();
|
||||
};
|
||||
|
|
|
@ -21,32 +21,6 @@ KeychainSecret::KeychainSecret() {}
|
|||
|
||||
KeychainSecret::~KeychainSecret() {}
|
||||
|
||||
nsresult KeychainSecret::Lock() {
|
||||
// https://developer.apple.com/documentation/security/1402180-seckeychainlock
|
||||
// Passing `nullptr` locks the default keychain.
|
||||
OSStatus rv = SecKeychainLock(nullptr);
|
||||
if (rv != errSecSuccess) {
|
||||
MOZ_LOG(gKeychainSecretLog, LogLevel::Debug,
|
||||
("SecKeychainLock failed: %d", rv));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult KeychainSecret::Unlock() {
|
||||
// https://developer.apple.com/documentation/security/1400341-seckeychainunlock
|
||||
// This attempts to unlock the default keychain. Using `false` indicates we
|
||||
// aren't passing in a password (if the keychain is locked, a dialog will
|
||||
// appear for the user).
|
||||
OSStatus rv = SecKeychainUnlock(nullptr, 0, nullptr, false);
|
||||
if (rv != errSecSuccess) {
|
||||
MOZ_LOG(gKeychainSecretLog, LogLevel::Debug,
|
||||
("SecKeychainUnlock failed: %d", rv));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ScopedCFType<CFStringRef> MozillaStringToCFString(const nsACString& stringIn) {
|
||||
// https://developer.apple.com/documentation/corefoundation/1543419-cfstringcreatewithbytes
|
||||
ScopedCFType<CFStringRef> stringOut(CFStringCreateWithBytes(
|
||||
|
|
|
@ -40,8 +40,6 @@ class KeychainSecret final : public AbstractOSKeyStore {
|
|||
virtual nsresult StoreSecret(const nsACString& secret,
|
||||
const nsACString& label) override;
|
||||
virtual nsresult DeleteSecret(const nsACString& label) override;
|
||||
virtual nsresult Lock() override;
|
||||
virtual nsresult Unlock() override;
|
||||
|
||||
virtual ~KeychainSecret();
|
||||
};
|
||||
|
|
|
@ -84,10 +84,6 @@ typedef SecretCollection* (*secret_collection_for_alias_sync_fn)(
|
|||
GError**);
|
||||
typedef SecretService* (*secret_service_get_sync_fn)(SecretServiceFlags,
|
||||
GCancellable*, GError**);
|
||||
typedef gint (*secret_service_lock_sync_fn)(SecretService*, GList*,
|
||||
GCancellable*, GList**, GError**);
|
||||
typedef gint (*secret_service_unlock_sync_fn)(SecretService*, GList*,
|
||||
GCancellable*, GList**, GError**);
|
||||
typedef gboolean (*secret_password_clear_sync_fn)(const SecretSchema*,
|
||||
GCancellable*, GError**, ...);
|
||||
typedef gchar* (*secret_password_lookup_sync_fn)(const SecretSchema*,
|
||||
|
@ -102,8 +98,6 @@ typedef GQuark (*secret_error_get_quark_fn)();
|
|||
static secret_collection_for_alias_sync_fn secret_collection_for_alias_sync =
|
||||
nullptr;
|
||||
static secret_service_get_sync_fn secret_service_get_sync = nullptr;
|
||||
static secret_service_lock_sync_fn secret_service_lock_sync = nullptr;
|
||||
static secret_service_unlock_sync_fn secret_service_unlock_sync = nullptr;
|
||||
static secret_password_clear_sync_fn secret_password_clear_sync = nullptr;
|
||||
static secret_password_lookup_sync_fn secret_password_lookup_sync = nullptr;
|
||||
static secret_password_store_sync_fn secret_password_store_sync = nullptr;
|
||||
|
@ -142,8 +136,6 @@ nsresult MaybeLoadLibSecret() {
|
|||
}
|
||||
FIND_FUNCTION_SYMBOL(secret_collection_for_alias_sync);
|
||||
FIND_FUNCTION_SYMBOL(secret_service_get_sync);
|
||||
FIND_FUNCTION_SYMBOL(secret_service_lock_sync);
|
||||
FIND_FUNCTION_SYMBOL(secret_service_unlock_sync);
|
||||
FIND_FUNCTION_SYMBOL(secret_password_clear_sync);
|
||||
FIND_FUNCTION_SYMBOL(secret_password_lookup_sync);
|
||||
FIND_FUNCTION_SYMBOL(secret_password_store_sync);
|
||||
|
@ -201,8 +193,6 @@ LibSecret::~LibSecret() {
|
|||
if (libsecret) {
|
||||
secret_collection_for_alias_sync = nullptr;
|
||||
secret_service_get_sync = nullptr;
|
||||
secret_service_lock_sync = nullptr;
|
||||
secret_service_unlock_sync = nullptr;
|
||||
secret_password_clear_sync = nullptr;
|
||||
secret_password_lookup_sync = nullptr;
|
||||
secret_password_store_sync = nullptr;
|
||||
|
@ -250,60 +240,6 @@ nsresult GetScopedServices(ScopedSecretService& aSs,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult LibSecret::Lock() {
|
||||
MOZ_ASSERT(secret_service_lock_sync);
|
||||
if (!secret_service_lock_sync) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ScopedSecretService ss;
|
||||
ScopedSecretCollection sc;
|
||||
if (NS_FAILED(GetScopedServices(ss, sc))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
GError* raw_error = nullptr;
|
||||
GList* collections = nullptr;
|
||||
ScopedGList collectionList(g_list_append(collections, sc.get()));
|
||||
int numLocked = secret_service_lock_sync(ss.get(), collectionList.get(),
|
||||
nullptr, // GCancellable
|
||||
nullptr, // list of locked items
|
||||
&raw_error);
|
||||
ScopedGError error(raw_error);
|
||||
if (numLocked != 1) {
|
||||
MOZ_LOG(gLibSecretLog, LogLevel::Debug,
|
||||
("Couldn't lock secret collection"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult LibSecret::Unlock() {
|
||||
MOZ_ASSERT(secret_service_unlock_sync);
|
||||
if (!secret_service_unlock_sync) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Accessing the secret service might unlock it.
|
||||
ScopedSecretService ss;
|
||||
ScopedSecretCollection sc;
|
||||
if (NS_FAILED(GetScopedServices(ss, sc))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
GError* raw_error = nullptr;
|
||||
GList* collections = nullptr;
|
||||
ScopedGList collectionList(g_list_append(collections, sc.get()));
|
||||
int numLocked = secret_service_unlock_sync(ss.get(), collectionList.get(),
|
||||
nullptr, // GCancellable
|
||||
nullptr, // list of unlocked items
|
||||
&raw_error);
|
||||
ScopedGError error(raw_error);
|
||||
if (numLocked != 1) {
|
||||
MOZ_LOG(gLibSecretLog, LogLevel::Debug,
|
||||
("Couldn't unlock secret collection"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult LibSecret::StoreSecret(const nsACString& aSecret,
|
||||
const nsACString& aLabel) {
|
||||
MOZ_ASSERT(secret_password_store_sync);
|
||||
|
|
|
@ -22,8 +22,6 @@ class LibSecret final : public AbstractOSKeyStore {
|
|||
virtual nsresult StoreSecret(const nsACString& secret,
|
||||
const nsACString& label) override;
|
||||
virtual nsresult DeleteSecret(const nsACString& label) override;
|
||||
virtual nsresult Lock() override;
|
||||
virtual nsresult Unlock() override;
|
||||
|
||||
virtual ~LibSecret();
|
||||
};
|
||||
|
|
|
@ -48,71 +48,9 @@ nsresult NSSKeyStore::InitToken() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NSSKeyStoreMainThreadLock(PK11SlotInfo* aSlot) {
|
||||
nsCOMPtr<nsIPK11Token> token = new nsPK11Token(aSlot);
|
||||
return token->LogoutSimple();
|
||||
}
|
||||
|
||||
nsresult NSSKeyStore::Lock() {
|
||||
NS_ENSURE_STATE(mSlot);
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIThread> mainThread;
|
||||
nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Forward to the main thread synchronously.
|
||||
SyncRunnable::DispatchToThread(
|
||||
mainThread, NS_NewRunnableFunction("NSSKeyStoreMainThreadLock",
|
||||
[slot = mSlot.get()]() {
|
||||
NSSKeyStoreMainThreadLock(slot);
|
||||
}));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NSSKeyStoreMainThreadLock(mSlot.get());
|
||||
}
|
||||
|
||||
nsresult NSSKeyStoreMainThreadUnlock(PK11SlotInfo* aSlot) {
|
||||
nsCOMPtr<nsIPK11Token> token = new nsPK11Token(aSlot);
|
||||
return NS_FAILED(token->Login(false /* force */)) ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
|
||||
nsresult NSSKeyStore::Unlock() {
|
||||
NS_ENSURE_STATE(mSlot);
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIThread> mainThread;
|
||||
nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Forward to the main thread synchronously.
|
||||
nsresult result = NS_ERROR_FAILURE;
|
||||
SyncRunnable::DispatchToThread(
|
||||
mainThread,
|
||||
NS_NewRunnableFunction("NSSKeyStoreMainThreadUnlock",
|
||||
[slot = mSlot.get(), result = &result]() {
|
||||
*result = NSSKeyStoreMainThreadUnlock(slot);
|
||||
}));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return NSSKeyStoreMainThreadUnlock(mSlot.get());
|
||||
}
|
||||
|
||||
nsresult NSSKeyStore::StoreSecret(const nsACString& aSecret,
|
||||
const nsACString& aLabel) {
|
||||
NS_ENSURE_STATE(mSlot);
|
||||
if (NS_FAILED(Unlock())) {
|
||||
MOZ_LOG(gNSSKeyStoreLog, LogLevel::Debug, ("Error unlocking NSS key db"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// It is possible for multiple keys to have the same nickname in NSS. To
|
||||
// prevent the problem of not knowing which key to use in the future, simply
|
||||
|
@ -159,10 +97,6 @@ nsresult NSSKeyStore::StoreSecret(const nsACString& aSecret,
|
|||
|
||||
nsresult NSSKeyStore::DeleteSecret(const nsACString& aLabel) {
|
||||
NS_ENSURE_STATE(mSlot);
|
||||
if (NS_FAILED(Unlock())) {
|
||||
MOZ_LOG(gNSSKeyStoreLog, LogLevel::Debug, ("Error unlocking NSS key db"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
UniquePK11SymKey symKey(PK11_ListFixedKeysInSlot(
|
||||
mSlot.get(), const_cast<char*>(PromiseFlatCString(aLabel).get()),
|
||||
|
@ -185,10 +119,6 @@ bool NSSKeyStore::SecretAvailable(const nsACString& aLabel) {
|
|||
if (!mSlot) {
|
||||
return false;
|
||||
}
|
||||
if (NS_FAILED(Unlock())) {
|
||||
MOZ_LOG(gNSSKeyStoreLog, LogLevel::Debug, ("Error unlocking NSS key db"));
|
||||
return false;
|
||||
}
|
||||
|
||||
UniquePK11SymKey symKey(PK11_ListFixedKeysInSlot(
|
||||
mSlot.get(), const_cast<char*>(PromiseFlatCString(aLabel).get()),
|
||||
|
@ -204,10 +134,6 @@ nsresult NSSKeyStore::EncryptDecrypt(const nsACString& aLabel,
|
|||
std::vector<uint8_t>& outBytes,
|
||||
bool encrypt) {
|
||||
NS_ENSURE_STATE(mSlot);
|
||||
if (NS_FAILED(Unlock())) {
|
||||
MOZ_LOG(gNSSKeyStoreLog, LogLevel::Debug, ("Error unlocking NSS key db"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
UniquePK11SymKey symKey(PK11_ListFixedKeysInSlot(
|
||||
mSlot.get(), const_cast<char*>(PromiseFlatCString(aLabel).get()),
|
||||
|
|
|
@ -19,8 +19,6 @@ class NSSKeyStore final : public AbstractOSKeyStore {
|
|||
virtual nsresult StoreSecret(const nsACString& secret,
|
||||
const nsACString& label) override;
|
||||
virtual nsresult DeleteSecret(const nsACString& label) override;
|
||||
virtual nsresult Lock() override;
|
||||
virtual nsresult Unlock() override;
|
||||
virtual nsresult EncryptDecrypt(const nsACString& label,
|
||||
const std::vector<uint8_t>& inBytes,
|
||||
std::vector<uint8_t>& outBytes,
|
||||
|
|
|
@ -28,7 +28,7 @@ NS_IMPL_ISUPPORTS(OSKeyStore, nsIOSKeyStore)
|
|||
using namespace mozilla;
|
||||
using dom::Promise;
|
||||
|
||||
OSKeyStore::OSKeyStore() : mKs(nullptr), mKsIsNSSKeyStore(false) {
|
||||
OSKeyStore::OSKeyStore() : mKs(nullptr) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (NS_WARN_IF(!NS_IsMainThread())) {
|
||||
return;
|
||||
|
@ -43,11 +43,9 @@ OSKeyStore::OSKeyStore() : mKs(nullptr), mKsIsNSSKeyStore(false) {
|
|||
mKs.reset(new LibSecret());
|
||||
} else {
|
||||
mKs.reset(new NSSKeyStore());
|
||||
mKsIsNSSKeyStore = true;
|
||||
}
|
||||
#else
|
||||
mKs.reset(new NSSKeyStore());
|
||||
mKsIsNSSKeyStore = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -185,23 +183,6 @@ nsresult OSKeyStore::DecryptBytes(const nsACString& aLabel,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult OSKeyStore::Lock() {
|
||||
NS_ENSURE_STATE(mKs);
|
||||
return mKs->Lock();
|
||||
}
|
||||
|
||||
nsresult OSKeyStore::Unlock() {
|
||||
NS_ENSURE_STATE(mKs);
|
||||
return mKs->Unlock();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
OSKeyStore::GetIsNSSKeyStore(bool* aNSSKeyStore) {
|
||||
NS_ENSURE_ARG_POINTER(aNSSKeyStore);
|
||||
*aNSSKeyStore = mKsIsNSSKeyStore;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Async interfaces that return promises because the key store implementation
|
||||
// might block, e.g. asking for a password.
|
||||
|
||||
|
@ -218,85 +199,6 @@ nsresult GetPromise(JSContext* aCx, /* out */ RefPtr<Promise>& aPromise) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void BackgroundUnlock(RefPtr<Promise>& aPromise, RefPtr<OSKeyStore> self) {
|
||||
nsAutoCString recovery;
|
||||
nsresult rv = self->Unlock();
|
||||
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
|
||||
"BackgroundUnlockOSKSResolve", [rv, aPromise = std::move(aPromise)]() {
|
||||
if (NS_FAILED(rv)) {
|
||||
aPromise->MaybeReject(rv);
|
||||
} else {
|
||||
aPromise->MaybeResolveWithUndefined();
|
||||
}
|
||||
}));
|
||||
NS_DispatchToMainThread(runnable.forget());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
OSKeyStore::AsyncUnlock(JSContext* aCx, Promise** promiseOut) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!NS_IsMainThread()) {
|
||||
return NS_ERROR_NOT_SAME_THREAD;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aCx);
|
||||
|
||||
RefPtr<Promise> promiseHandle;
|
||||
nsresult rv = GetPromise(aCx, promiseHandle);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
RefPtr<OSKeyStore> self = this;
|
||||
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
|
||||
"BackgroundUnlock", [self, promiseHandle]() mutable {
|
||||
BackgroundUnlock(promiseHandle, self);
|
||||
}));
|
||||
|
||||
promiseHandle.forget(promiseOut);
|
||||
return NS_DispatchBackgroundTask(runnable.forget(),
|
||||
NS_DISPATCH_EVENT_MAY_BLOCK);
|
||||
}
|
||||
|
||||
void BackgroundLock(RefPtr<Promise>& aPromise, RefPtr<OSKeyStore> self) {
|
||||
nsresult rv = self->Lock();
|
||||
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
|
||||
"BackgroundLockOSKSResolve", [rv, aPromise = std::move(aPromise)]() {
|
||||
if (NS_FAILED(rv)) {
|
||||
aPromise->MaybeReject(rv);
|
||||
} else {
|
||||
aPromise->MaybeResolveWithUndefined();
|
||||
}
|
||||
}));
|
||||
NS_DispatchToMainThread(runnable.forget());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
OSKeyStore::AsyncLock(JSContext* aCx, Promise** promiseOut) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!NS_IsMainThread()) {
|
||||
return NS_ERROR_NOT_SAME_THREAD;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aCx);
|
||||
|
||||
RefPtr<Promise> promiseHandle;
|
||||
nsresult rv = GetPromise(aCx, promiseHandle);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
RefPtr<OSKeyStore> self = this;
|
||||
nsCOMPtr<nsIRunnable> runnable(
|
||||
NS_NewRunnableFunction("BackgroundLock", [self, promiseHandle]() mutable {
|
||||
BackgroundLock(promiseHandle, self);
|
||||
}));
|
||||
|
||||
promiseHandle.forget(promiseOut);
|
||||
return NS_DispatchBackgroundTask(runnable.forget(),
|
||||
NS_DISPATCH_EVENT_MAY_BLOCK);
|
||||
}
|
||||
|
||||
void BackgroundGenerateSecret(const nsACString& aLabel,
|
||||
RefPtr<Promise>& aPromise,
|
||||
RefPtr<OSKeyStore> self) {
|
||||
|
|
|
@ -28,10 +28,6 @@ class AbstractOSKeyStore {
|
|||
const nsACString& label) = 0;
|
||||
// Delete the secret with the given label.
|
||||
virtual nsresult DeleteSecret(const nsACString& label) = 0;
|
||||
// Lock the key store.
|
||||
virtual nsresult Lock() = 0;
|
||||
// Unlock the key store.
|
||||
virtual nsresult Unlock() = 0;
|
||||
virtual ~AbstractOSKeyStore() = default;
|
||||
|
||||
// Returns true if the secret with the given label is available in the key
|
||||
|
@ -92,14 +88,11 @@ class OSKeyStore final : public nsIOSKeyStore {
|
|||
const nsACString& aEncryptedBase64Text,
|
||||
/*out*/ uint32_t* outLen,
|
||||
/*out*/ uint8_t** outBytes);
|
||||
nsresult Lock();
|
||||
nsresult Unlock();
|
||||
|
||||
private:
|
||||
~OSKeyStore() = default;
|
||||
|
||||
std::unique_ptr<AbstractOSKeyStore> mKs;
|
||||
bool mKsIsNSSKeyStore;
|
||||
};
|
||||
|
||||
#endif // OSKeyStore_h
|
||||
|
|
|
@ -12,18 +12,15 @@ interface nsIOSKeyStore: nsISupports {
|
|||
* rest. The key used to encrypt and decrypt the data is stored in the OS
|
||||
* key store.
|
||||
*
|
||||
* NB: To first authenticate the user to the system, use
|
||||
* nsIOSReauthenticator.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* // obtain the singleton OSKeyStore instance
|
||||
* const oskeystore = Cc["@mozilla.org/security/oskeystore;1"].getService(Ci.nsIOSKeyStore);
|
||||
*
|
||||
* const PASSWORD_LABEL = "mylabel1";
|
||||
* const COOKIE_LABEL = "mylabel2";
|
||||
*
|
||||
* // Unlock the key store.
|
||||
* // Note that this is not necesssary. The key store will be unlocked
|
||||
* // automatically when an operation is performed on it.
|
||||
* await oskeystore.asyncUnlock();
|
||||
*
|
||||
* // Check if there's a secret for your label already.
|
||||
* if (!await oskeystore.asyncSecretAvailable(PASSWORD_LABEL)) {
|
||||
|
@ -42,9 +39,6 @@ interface nsIOSKeyStore: nsISupports {
|
|||
*
|
||||
* // Recover a secret from a recovery code.
|
||||
* await oskeystore.asyncRecoverSecret(PASSWORD_LABEL, recoveryPhrase);
|
||||
*
|
||||
* // Lock the key store to prompt the user to log into her OS key store again.
|
||||
* await oskeystore.asyncLock();
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -115,30 +109,4 @@ interface nsIOSKeyStore: nsISupports {
|
|||
*/
|
||||
[implicit_jscontext, must_use]
|
||||
Promise asyncDecryptBytes(in ACString label, in ACString encryptedBase64Text);
|
||||
|
||||
/**
|
||||
* Lock the key store.
|
||||
* The actual behaviour of this depends on the OS.
|
||||
*
|
||||
* @return Promise resolving to undefined or an error.
|
||||
*/
|
||||
[implicit_jscontext, must_use]
|
||||
Promise asyncLock();
|
||||
|
||||
/**
|
||||
* Unlock the key store.
|
||||
* The actual behaviour of this depends on the OS.
|
||||
*
|
||||
* @return Promise resolving to undefined or an error.
|
||||
*/
|
||||
[implicit_jscontext, must_use]
|
||||
Promise asyncUnlock();
|
||||
|
||||
|
||||
/**
|
||||
* Check if the implementation is using the NSS key store.
|
||||
* This is a special case because Firefox has to handle the locking and
|
||||
* unlocking.
|
||||
*/
|
||||
readonly attribute bool isNSSKeyStore;
|
||||
};
|
||||
|
|
|
@ -25,46 +25,6 @@ async function delete_all_secrets() {
|
|||
}
|
||||
}
|
||||
|
||||
// Test that Firefox handles locking and unlocking of the OSKeyStore properly.
|
||||
// Does so by mocking out the actual dialog and "filling in" the
|
||||
// password. Also tests that providing an incorrect password will fail (well,
|
||||
// technically the user will just get prompted again, but if they then cancel
|
||||
// the dialog the overall operation will fail).
|
||||
|
||||
var gMockPrompter = {
|
||||
passwordToTry: null,
|
||||
numPrompts: 0,
|
||||
|
||||
// This intentionally does not use arrow function syntax to avoid an issue
|
||||
// where in the context of the arrow function, |this != gMockPrompter| due to
|
||||
// how objects get wrapped when going across xpcom boundaries.
|
||||
promptPassword(dialogTitle, text, password, checkMsg, checkValue) {
|
||||
this.numPrompts++;
|
||||
equal(
|
||||
text,
|
||||
"Please enter your Primary Password.",
|
||||
"password prompt text should be as expected"
|
||||
);
|
||||
equal(checkMsg, null, "checkMsg should be null");
|
||||
ok(this.passwordToTry, "passwordToTry should be non-null");
|
||||
if (this.passwordToTry == "DontTryThisPassword") {
|
||||
// Cancel the prompt in this case.
|
||||
return false;
|
||||
}
|
||||
password.value = this.passwordToTry;
|
||||
return true;
|
||||
},
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI(["nsIPrompt"]),
|
||||
};
|
||||
|
||||
// Mock nsIWindowWatcher. PSM calls getNewPrompter on this to get an nsIPrompt
|
||||
// to call promptPassword. We return the mock one, above.
|
||||
var gWindowWatcher = {
|
||||
getNewPrompter: () => gMockPrompter,
|
||||
QueryInterface: ChromeUtils.generateQI(["nsIWindowWatcher"]),
|
||||
};
|
||||
|
||||
async function encrypt_decrypt_test() {
|
||||
let keystore = Cc["@mozilla.org/security/oskeystore;1"].getService(
|
||||
Ci.nsIOSKeyStore
|
||||
|
@ -109,110 +69,9 @@ async function encrypt_decrypt_test() {
|
|||
}
|
||||
|
||||
add_task(async function () {
|
||||
let keystore = Cc["@mozilla.org/security/oskeystore;1"].getService(
|
||||
Ci.nsIOSKeyStore
|
||||
);
|
||||
let windowWatcherCID;
|
||||
if (keystore.isNSSKeyStore) {
|
||||
windowWatcherCID = MockRegistrar.register(
|
||||
"@mozilla.org/embedcomp/window-watcher;1",
|
||||
gWindowWatcher
|
||||
);
|
||||
registerCleanupFunction(() => {
|
||||
MockRegistrar.unregister(windowWatcherCID);
|
||||
});
|
||||
}
|
||||
|
||||
await delete_all_secrets();
|
||||
await encrypt_decrypt_test();
|
||||
await delete_all_secrets();
|
||||
|
||||
if (
|
||||
AppConstants.platform == "macosx" ||
|
||||
AppConstants.platform == "win" ||
|
||||
AppConstants.platform == "linux"
|
||||
) {
|
||||
ok(
|
||||
!keystore.isNSSKeyStore,
|
||||
"OS X, Windows, and Linux should use the non-NSS implementation"
|
||||
);
|
||||
}
|
||||
|
||||
if (keystore.isNSSKeyStore) {
|
||||
// If we use the NSS key store implementation test that everything works
|
||||
// when a master password is set.
|
||||
// Set an initial password.
|
||||
let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"].getService(
|
||||
Ci.nsIPK11TokenDB
|
||||
);
|
||||
let token = tokenDB.getInternalKeyToken();
|
||||
token.initPassword("hunter2");
|
||||
|
||||
// Lock the key store. This should be equivalent to token.logoutSimple()
|
||||
await keystore.asyncLock();
|
||||
|
||||
// Set the correct password so that the test operations should succeed.
|
||||
gMockPrompter.passwordToTry = "hunter2";
|
||||
await encrypt_decrypt_test();
|
||||
ok(
|
||||
gMockPrompter.numPrompts == 1,
|
||||
"There should've been one password prompt."
|
||||
);
|
||||
await delete_all_secrets();
|
||||
}
|
||||
|
||||
// Check lock/unlock behaviour.
|
||||
// Unfortunately we can only test this automatically for the NSS key store.
|
||||
// Uncomment the outer keystore.isNSSKeyStore to test other key stores manually.
|
||||
if (keystore.isNSSKeyStore) {
|
||||
await delete_all_secrets();
|
||||
await encrypt_decrypt_test();
|
||||
await keystore.asyncLock();
|
||||
info("Keystore should be locked. Cancel the login request.");
|
||||
try {
|
||||
if (keystore.isNSSKeyStore) {
|
||||
gMockPrompter.passwordToTry = "DontTryThisPassword";
|
||||
}
|
||||
await keystore.asyncUnlock();
|
||||
ok(false, "Unlock should've rejected.");
|
||||
} catch (e) {
|
||||
ok(
|
||||
e.result == Cr.NS_ERROR_FAILURE || e.result == Cr.NS_ERROR_ABORT,
|
||||
"Rejected login prompt."
|
||||
);
|
||||
}
|
||||
// clean up
|
||||
if (keystore.isNSSKeyStore) {
|
||||
gMockPrompter.passwordToTry = "hunter2";
|
||||
}
|
||||
await delete_all_secrets();
|
||||
}
|
||||
});
|
||||
|
||||
// Test that if we kick off a background operation and then call a synchronous function on the
|
||||
// keystore, we don't deadlock.
|
||||
add_task(async function () {
|
||||
await delete_all_secrets();
|
||||
|
||||
let keystore = Cc["@mozilla.org/security/oskeystore;1"].getService(
|
||||
Ci.nsIOSKeyStore
|
||||
);
|
||||
let recoveryPhrase = await keystore.asyncGenerateSecret(LABELS[0]);
|
||||
ok(recoveryPhrase, "A recovery phrase should've been created.");
|
||||
|
||||
try {
|
||||
let text = new Uint8Array(8192);
|
||||
let promise = keystore.asyncEncryptBytes(LABELS[0], text);
|
||||
/* eslint-disable no-unused-expressions */
|
||||
keystore.isNSSKeyStore; // we don't care what this is - we just need to access it
|
||||
/* eslint-enable no-unused-expressions */
|
||||
let ciphertext = await promise;
|
||||
ok(ciphertext, "We should have a ciphertext now.");
|
||||
} catch (e) {
|
||||
ok(false, "Error encrypting " + e);
|
||||
}
|
||||
|
||||
await delete_all_secrets();
|
||||
});
|
||||
|
||||
// Test that using a recovery phrase works.
|
||||
|
|
Загрузка…
Ссылка в новой задаче