Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  TestLockstoreKeystore.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "gtest/gtest.h"

#include "mozilla/gtest/MozAssertions.h"
#include "mozilla/security/lockstore/lockstore_ffi_generated.h"
#include "nsCOMPtr.h"
#include "nsDirectoryServiceDefs.h"
#include "nsIFile.h"
#include "nsString.h"
#include "nsTArray.h"

using mozilla::security::lockstore::keystore_add_kek;
using mozilla::security::lockstore::keystore_close;
using mozilla::security::lockstore::keystore_create_dek;
using mozilla::security::lockstore::keystore_create_kek;
using mozilla::security::lockstore::keystore_decrypt;
using mozilla::security::lockstore::keystore_delete_dek;
using mozilla::security::lockstore::keystore_encrypt;
using mozilla::security::lockstore::keystore_get_dek;
using mozilla::security::lockstore::keystore_import_dek;
using mozilla::security::lockstore::keystore_is_dek_extractable;
using mozilla::security::lockstore::keystore_is_kek_unlocked;
using mozilla::security::lockstore::keystore_list_deks;
using mozilla::security::lockstore::keystore_lock;
using mozilla::security::lockstore::keystore_lock_kek;
using mozilla::security::lockstore::keystore_open;
using mozilla::security::lockstore::keystore_remove_kek;
using mozilla::security::lockstore::keystore_switch_kek;
using mozilla::security::lockstore::keystore_unlock_kek;
using mozilla::security::lockstore::KeystoreHandle;

class LockstoreKeystoreTest : public ::testing::Test {
 protected:
  nsCOMPtr<nsIFile> mTmpDir;
  nsAutoCString mProfilePath;
  KeystoreHandle* mKeystore = nullptr;
  // Per-test LocalKey kek_ref. LocalKey is no longer a canonical
  // singleton: every test mints its own via createKek("local", ...)
  // and uses the returned random-ID kek_ref throughout.
  nsCString mLocalKekRef;

  void SetUp() override {
    nsresult rv =
        NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mTmpDir));
    ASSERT_NS_SUCCEEDED(rv);
    rv = mTmpDir->AppendNative("lockstore_ks_test"_ns);
    ASSERT_NS_SUCCEEDED(rv);
    rv = mTmpDir->CreateUnique(nsIFile::DIRECTORY_TYPE, 0700);
    ASSERT_NS_SUCCEEDED(rv);
    nsAutoString profilePathWide;
    rv = mTmpDir->GetPath(profilePathWide);
    ASSERT_NS_SUCCEEDED(rv);
    mProfilePath = NS_ConvertUTF16toUTF8(profilePathWide);
  }

  void TearDown() override {
    if (mKeystore) {
      EXPECT_NS_SUCCEEDED(keystore_close(mKeystore));
      mKeystore = nullptr;
    }
    if (mTmpDir) {
      mTmpDir->Remove(true);
    }
  }

  // Mint a fresh LocalKey kek_ref against the already-open keystore
  // and store it in `mLocalKekRef`. Call this after a successful
  // `keystore_open` whenever the test needs a usable
  // LocalKey to wrap a DEK under.
  void MintLocalKek() {
    const nsCString kekType("local"_ns);
    const nsCString empty;
    nsresult rv = keystore_create_kek(mKeystore, &kekType, &empty, &empty,
                                      /* cache_timeout_ms */ 0, &mLocalKekRef);
    ASSERT_NS_SUCCEEDED(rv);
  }

  // Mint a fresh Password kek_ref against the already-open keystore.
  // The unlocked KEK is NOT cached on creation; callers must invoke
  // keystore_unlock_kek before any DEK op against it.
  void MintPassword(const nsACString& aPassword, nsCString& aOut) {
    const nsCString kekType("password"_ns);
    const nsCString empty;
    nsresult rv = keystore_create_kek(mKeystore, &kekType, &empty, &aPassword,
                                      /* cache_timeout_ms */ 0, &aOut);
    ASSERT_NS_SUCCEEDED(rv);
  }
};

TEST_F(LockstoreKeystoreTest, OpenAndClose) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();
  ASSERT_NE(mKeystore, nullptr);
  nsresult rvClose = keystore_close(mKeystore);
  mKeystore = nullptr;
  ASSERT_NS_SUCCEEDED(rvClose);
}

TEST_F(LockstoreKeystoreTest, OpenEmptyPath) {
  nsAutoCString empty;
  nsresult rv = keystore_open(&empty, &mKeystore);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
  ASSERT_EQ(mKeystore, nullptr);
}

TEST_F(LockstoreKeystoreTest, CreateAndListDek) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("mycoll");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  nsTArray<nsCString> collections;
  rv = keystore_list_deks(mKeystore, &collections);
  ASSERT_NS_SUCCEEDED(rv);
  ASSERT_EQ(collections.Length(), 1u);
  EXPECT_EQ(collections[0], coll);
}

TEST_F(LockstoreKeystoreTest, CreateDekEmptyCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  nsAutoCString empty;
  rv = keystore_create_dek(mKeystore, &empty, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, CreateDekDuplicate) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("dup");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_EQ(rv, NS_ERROR_FAILURE);
}

TEST_F(LockstoreKeystoreTest, GetDekExtractable) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("extract");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, true,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  nsTArray<uint8_t> dek;
  rv = keystore_get_dek(mKeystore, &coll, &mLocalKekRef, &dek);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_GT(dek.Length(), 0u);
}

TEST_F(LockstoreKeystoreTest, GetDekEmptyCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  nsAutoCString empty;
  nsTArray<uint8_t> dek;
  rv = keystore_get_dek(mKeystore, &empty, &mLocalKekRef, &dek);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, GetDekNonexistent) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("nosuch");
  nsTArray<uint8_t> dek;
  rv = keystore_get_dek(mKeystore, &coll, &mLocalKekRef, &dek);
  ASSERT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
}

TEST_F(LockstoreKeystoreTest, GetDekNotExtractable) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("noextract");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  nsTArray<uint8_t> dek;
  rv = keystore_get_dek(mKeystore, &coll, &mLocalKekRef, &dek);
  ASSERT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
}

TEST_F(LockstoreKeystoreTest, DeleteDek) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("todelete");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  rv = keystore_delete_dek(mKeystore, &coll);
  ASSERT_NS_SUCCEEDED(rv);

  nsTArray<nsCString> collections;
  rv = keystore_list_deks(mKeystore, &collections);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_EQ(collections.Length(), 0u);
}

TEST_F(LockstoreKeystoreTest, DeleteDekEmptyCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  nsAutoCString empty;
  rv = keystore_delete_dek(mKeystore, &empty);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, DeleteDekNonexistent) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("nosuch");
  rv = keystore_delete_dek(mKeystore, &coll);
  ASSERT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
}

TEST_F(LockstoreKeystoreTest, ListCollectionsEmpty) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  nsTArray<nsCString> collections;
  rv = keystore_list_deks(mKeystore, &collections);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_EQ(collections.Length(), 0u);
}

TEST_F(LockstoreKeystoreTest, ListMultipleCollections) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString alpha("alpha");
  const nsCString beta("beta");
  const nsCString gamma("gamma");
  rv = keystore_create_dek(mKeystore, &alpha, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);
  rv = keystore_create_dek(mKeystore, &beta, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);
  rv = keystore_create_dek(mKeystore, &gamma, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  nsTArray<nsCString> collections;
  rv = keystore_list_deks(mKeystore, &collections);
  ASSERT_NS_SUCCEEDED(rv);
  ASSERT_EQ(collections.Length(), 3u);
  EXPECT_TRUE(collections.Contains(alpha));
  EXPECT_TRUE(collections.Contains(beta));
  EXPECT_TRUE(collections.Contains(gamma));
}

TEST_F(LockstoreKeystoreTest, PersistenceAcrossReopen) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("persist");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  ASSERT_NS_SUCCEEDED(keystore_close(mKeystore));
  mKeystore = nullptr;

  rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);

  nsTArray<nsCString> collections;
  rv = keystore_list_deks(mKeystore, &collections);
  ASSERT_NS_SUCCEEDED(rv);
  ASSERT_EQ(collections.Length(), 1u);
  EXPECT_EQ(collections[0], coll);
}

TEST_F(LockstoreKeystoreTest, AddKekEmptyCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  nsAutoCString empty;
  rv = keystore_add_kek(mKeystore, &empty, &mLocalKekRef, &mLocalKekRef);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, AddKekNonexistentCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("nosuch");
  rv = keystore_add_kek(mKeystore, &coll, &mLocalKekRef, &mLocalKekRef);
  ASSERT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
}

TEST_F(LockstoreKeystoreTest, AddKekDuplicate) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("adddup");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  rv = keystore_add_kek(mKeystore, &coll, &mLocalKekRef, &mLocalKekRef);
  ASSERT_EQ(rv, NS_ERROR_FAILURE);
}

TEST_F(LockstoreKeystoreTest, RemoveKekEmptyCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  nsAutoCString empty;
  rv = keystore_remove_kek(mKeystore, &empty, &mLocalKekRef);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, RemoveKekNonexistentCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("nosuch");
  rv = keystore_remove_kek(mKeystore, &coll, &mLocalKekRef);
  ASSERT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
}

TEST_F(LockstoreKeystoreTest, RemoveKekLastRemaining) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("removelast");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  rv = keystore_remove_kek(mKeystore, &coll, &mLocalKekRef);
  ASSERT_EQ(rv, NS_ERROR_FAILURE);
}

TEST_F(LockstoreKeystoreTest, EncryptDecryptRoundtrip) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("crypto");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  const uint8_t plaintext[] = {'h''e''l''l''o'};
  nsTArray<uint8_t> ciphertext;
  rv = keystore_encrypt(mKeystore, &coll, &mLocalKekRef, plaintext,
                        sizeof(plaintext), &ciphertext);
  ASSERT_NS_SUCCEEDED(rv);
  ASSERT_GT(ciphertext.Length(), sizeof(plaintext));

  nsTArray<uint8_t> round;
  rv = keystore_decrypt(mKeystore, &coll, &mLocalKekRef, ciphertext.Elements(),
                        ciphertext.Length(), &round);
  ASSERT_NS_SUCCEEDED(rv);
  ASSERT_EQ(round.Length(), sizeof(plaintext));
  EXPECT_EQ(memcmp(round.Elements(), plaintext, sizeof(plaintext)), 0);
}

TEST_F(LockstoreKeystoreTest, EncryptEmptyCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  nsAutoCString empty;
  const uint8_t plaintext[] = {'x'};
  nsTArray<uint8_t> ciphertext;
  rv = keystore_encrypt(mKeystore, &empty, &mLocalKekRef, plaintext,
                        sizeof(plaintext), &ciphertext);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, EncryptUnknownCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("nosuch");
  const uint8_t plaintext[] = {'x'};
  nsTArray<uint8_t> ciphertext;
  rv = keystore_encrypt(mKeystore, &coll, &mLocalKekRef, plaintext,
                        sizeof(plaintext), &ciphertext);
  ASSERT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
}

TEST_F(LockstoreKeystoreTest, DecryptEmptyCiphertext) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("decempty");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  nsTArray<uint8_t> plaintext;
  rv =
      keystore_decrypt(mKeystore, &coll, &mLocalKekRef, nullptr, 0, &plaintext);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, IsKekUnlockedLocalAlwaysTrue) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  // LocalKey has no interactive gate, so it's always reported unlocked.
  bool unlocked = false;
  rv = keystore_is_kek_unlocked(mKeystore, &mLocalKekRef, &unlocked);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_TRUE(unlocked);
}

TEST_F(LockstoreKeystoreTest, IsKekUnlockedPasswordInitiallyFalse) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);

  // A freshly-minted Password kek_ref starts locked: createKek persists
  // the wrapped KEK but does not populate the unlock cache.
  nsCString pwKekRef;
  MintPassword("hunter2"_ns, pwKekRef);
  bool unlocked = true;
  rv = keystore_is_kek_unlocked(mKeystore, &pwKekRef, &unlocked);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_FALSE(unlocked);
}

TEST_F(LockstoreKeystoreTest, LockKekEmptyRef) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  nsAutoCString empty;
  rv = keystore_lock_kek(mKeystore, &empty);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, LockKekLocalIsNoop) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  // LocalKey lock/unlock never fail; they're no-ops.
  rv = keystore_lock_kek(mKeystore, &mLocalKekRef);
  ASSERT_NS_SUCCEEDED(rv);
}

TEST_F(LockstoreKeystoreTest, UnlockKekPasswordUnknownRefFails) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);

  // A `password:` kek_ref that has no persisted record surfaces
  // InvalidKekRef → NS_ERROR_INVALID_ARG when callers try to unlock it.
  const nsCString bogusPw("lockstore::kek::password:not-a-real-id"_ns);
  const nsCString pw("pw"_ns);
  rv = keystore_unlock_kek(mKeystore, &bogusPw, &pw,
                           /* timeoutMs */ 60000);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, UnlockKekUnknownRefFails) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString bogus("lockstore::kek::bogus"_ns);
  const nsCString pw("pw"_ns);
  rv = keystore_unlock_kek(mKeystore, &bogus, &pw,
                           /* timeoutMs */ 60000);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, GetDekForPasswordWhenLockedFails) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);

  // Freshly-minted Password kek_ref starts locked. Creating a DEK
  // under it must fail with NS_ERROR_NOT_AVAILABLE (Locked) until the
  // caller invokes unlock_kek.
  nsCString pwKekRef;
  MintPassword("hunter2"_ns, pwKekRef);
  const nsCString coll("pwlocked");
  rv = keystore_create_dek(mKeystore, &coll, &pwKekRef, false/*key_size=*/32);
  ASSERT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
}

TEST_F(LockstoreKeystoreTest, LockAllIsNoopWhenNothingCached) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  // `lock()` clears every cached KEK. With nothing cached it must still
  // succeed (callers on shutdown shouldn't have to check first).
  rv = keystore_lock(mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
}

TEST_F(LockstoreKeystoreTest, ImportDekRoundtripExtractable) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("imported");
  uint8_t dek[32];
  for (size_t i = 0; i < sizeof(dek); ++i) {
    dek[i] = static_cast<uint8_t>(i + 1);
  }
  rv = keystore_import_dek(mKeystore, &coll, &mLocalKekRef, dek, sizeof(dek),
                           true);
  ASSERT_NS_SUCCEEDED(rv);

  nsTArray<uint8_t> round;
  rv = keystore_get_dek(mKeystore, &coll, &mLocalKekRef, &round);
  ASSERT_NS_SUCCEEDED(rv);
  ASSERT_EQ(round.Length(), sizeof(dek));
  for (size_t i = 0; i < sizeof(dek); ++i) {
    EXPECT_EQ(round[i], dek[i]);
  }
}

TEST_F(LockstoreKeystoreTest, ImportDekWrongLength) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("badlen");
  uint8_t shortDek[16] = {0};
  rv = keystore_import_dek(mKeystore, &coll, &mLocalKekRef, shortDek,
                           sizeof(shortDek), true);
  ASSERT_EQ(rv, NS_ERROR_FAILURE);
}

TEST_F(LockstoreKeystoreTest, ImportDekEmptyCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  nsAutoCString empty;
  uint8_t dek[32] = {0};
  rv = keystore_import_dek(mKeystore, &empty, &mLocalKekRef, dek, sizeof(dek),
                           true);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, ImportDekDuplicate) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("dup");
  uint8_t dek[32] = {0};
  rv = keystore_import_dek(mKeystore, &coll, &mLocalKekRef, dek, sizeof(dek),
                           true);
  ASSERT_NS_SUCCEEDED(rv);

  rv = keystore_import_dek(mKeystore, &coll, &mLocalKekRef, dek, sizeof(dek),
                           true);
  ASSERT_EQ(rv, NS_ERROR_FAILURE);
}

TEST_F(LockstoreKeystoreTest, IsDekExtractableTrue) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("extract-yes");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, true,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  bool extractable = false;
  rv = keystore_is_dek_extractable(mKeystore, &coll, &extractable);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_TRUE(extractable);
}

TEST_F(LockstoreKeystoreTest, IsDekExtractableFalse) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("extract-no");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  bool extractable = true;
  rv = keystore_is_dek_extractable(mKeystore, &coll, &extractable);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_FALSE(extractable);
}

TEST_F(LockstoreKeystoreTest, IsDekExtractableMissingCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("nope");
  bool extractable = false;
  rv = keystore_is_dek_extractable(mKeystore, &coll, &extractable);
  ASSERT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
}

TEST_F(LockstoreKeystoreTest, IsDekExtractableEmptyCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  nsAutoCString empty;
  bool extractable = false;
  rv = keystore_is_dek_extractable(mKeystore, &empty, &extractable);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, SwitchKekEmptyArgs) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  nsAutoCString empty;
  const nsCString coll("col");
  rv = keystore_switch_kek(mKeystore, &empty, &mLocalKekRef, &mLocalKekRef);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
  rv = keystore_switch_kek(mKeystore, &coll, &empty, &mLocalKekRef);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
  rv = keystore_switch_kek(mKeystore, &coll, &mLocalKekRef, &empty);
  ASSERT_EQ(rv, NS_ERROR_INVALID_ARG);
}

TEST_F(LockstoreKeystoreTest, SwitchKekSameRefRejected) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  const nsCString coll("col");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  rv = keystore_switch_kek(mKeystore, &coll, &mLocalKekRef, &mLocalKekRef);
  // old == new is InvalidConfiguration → NS_ERROR_FAILURE per the FFI mapping.
  ASSERT_EQ(rv, NS_ERROR_FAILURE);
}

TEST_F(LockstoreKeystoreTest, SwitchKekNonexistentCollection) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  // Switching against a collection that doesn't exist must reject
  // before the kek_ref types are even consulted.
  const nsCString coll("nope");
  nsCString otherLocal;
  {
    const nsCString kekType("local"_ns);
    const nsCString empty;
    rv = keystore_create_kek(mKeystore, &kekType, &empty, &empty, 0,
                             &otherLocal);
    ASSERT_NS_SUCCEEDED(rv);
  }
  rv = keystore_switch_kek(mKeystore, &coll, &mLocalKekRef, &otherLocal);
  ASSERT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
}

TEST_F(LockstoreKeystoreTest, SwitchKekMissingOldWrapping) {
  nsresult rv = keystore_open(&mProfilePath, &mKeystore);
  ASSERT_NS_SUCCEEDED(rv);
  MintLocalKek();

  // Collection wrapped only under LocalKey; "switch from <another Local>"
  // must reject because that other ref doesn't currently wrap this
  // collection.
  const nsCString coll("local-only");
  rv = keystore_create_dek(mKeystore, &coll, &mLocalKekRef, false,
                           /*key_size=*/32);
  ASSERT_NS_SUCCEEDED(rv);

  nsCString otherLocal;
  {
    const nsCString kekType("local"_ns);
    const nsCString empty;
    rv = keystore_create_kek(mKeystore, &kekType, &empty, &empty, 0,
                             &otherLocal);
    ASSERT_NS_SUCCEEDED(rv);
  }
  rv = keystore_switch_kek(mKeystore, &coll, &otherLocal, &mLocalKekRef);
  ASSERT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
}

Messung V0.5 in Prozent
C=86 H=98 G=91

¤ Dauer der Verarbeitung: 0.9 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002