FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Intel Software Guard Extensionのチュートリアル サンプルプログラムを実行(Part-3 PasswordManagerCore)

Intel SGX Tutorialを読み進めているのだが、サンプルプログラムにも触れておきたい。

まずはPart-3のサンプルコードから。いわゆる普通のソフトウェアとか、GUIのソフトウェアとか触る機会がないので扱い方に少し戸惑うが...

software.intel.com

ページの一番最後にダウンロードのリンクがあるのでそれを経由してダウンロードする。

f:id:msyksphinz:20180827230914p:plain

Visual Studio 2017で開いた。メインプログラムはC#で記述されている。

f:id:msyksphinz:20180827231037p:plain

実行するとこのようになる。CUIのプログラムなのでテキストがパラパラと出てきて終了である。 が、最後FAILと表示されているじゃないか。何だこりゃ。

f:id:msyksphinz:20180827231131p:plain
=========================================================
NEW VAULT TESTS
=========================================================
Deleting test vault C:\Users\msyksphinz\Documents\test1.vlt
Creating new test vault C:\Users\msyksphinz\Documents\test1.vlt
    Expected 0, received 0...>>> PASS <<<
Unlock before creating a password
    Expected 8, received 8...>>> PASS <<<
Random password
    Expected 0, received 0...>>> PASS <<<
Add account before creating password
    Expected 8, received 8...>>> PASS <<<
Set master password
    Expected 0, received 0...>>> PASS <<<
Get number of accounts
    Expected 0, received 0...>>> PASS <<<
Found 0 accounts
    Expected 0, received 0...>>> PASS <<<
Set/add info at account index 3
    Expected 0, received 0...>>> PASS <<<
Get number of accounts
    Expected 0, received 0...>>> PASS <<<
Found 4 accounts
    Expected 4, received 4...>>> PASS <<<
Account 0:
    Expected 0, received 0...>>> PASS <<<
    Name =
   Login =
     URL =
    Expected 0, received 0...>>> PASS <<<
Password =
Account 1:
    Expected 0, received 0...>>> PASS <<<
    Name =
   Login =
     URL =
    Expected 0, received 0...>>> PASS <<<
Password =
Account 2:
    Expected 0, received 0...>>> PASS <<<
    Name =
   Login =
     URL =
    Expected 0, received 0...>>> PASS <<<
Password =
Account 3:
    Expected 0, received 0...>>> PASS <<<
    Name = IRC
   Login = jellybean
     URL = n/a
    Expected 0, received 0...>>> PASS <<<
Password =
Locking vault
Unlocking vault
    Expected 0, received 0...>>> PASS <<<
Get number of accounts
    Expected 0, received 0...>>> PASS <<<
Found 1 accounts
    Expected 1, received 1...>>> PASS <<<
Account 0:
    Expected 0, received 0...>>> PASS <<<
    Name = IRC
   Login = jellybean
     URL = n/a
    Expected 0, received 0...>>> PASS <<<
Password =
=========================================================
EXISTING VAULT TESTS
=========================================================
Checking for reference vault C:\Users\msyksphinz\Documents\reference.vlt
    Expected True, received False...>>> FAIL <<<
Hit ENTER to exit...

何をしているのか

  • TestSuite.cs
        public bool RunAll()
        {
           try {
                this.Initialize();
                this.RunNewVault();
                this.RunExistingVault();
           }
           catch {                
                return false;
           }
        }

mgr.vault_createによりパスワード管理クラス(PasswordManagerCore)を作成しているらしい。

  • TestSuite.cs
        PasswordManagerCore mgr;
...
            // Create a new vault
            Console.WriteLine("Creating new test vault {0}", path);
            rv= mgr.vault_create(path);

一つ一つ追っていくことにした。 コメントを追いかけると次のようなテストをしていることになる。

RunNewVault

  1. テスト用のvaultを作成する。
  2. vaultをアンロックする。
  3. ランダムなパスワードを作成する。
  4. パスワードなしでアカウントを追加する。これは失敗するはずである。
  5. スターパスワードを設定する。マスターパスワードは3.とは異なる。ここでは"12345@#$%asdfg"としている。
  6. アカウント数を確認する。ここでは4.で失敗したので0のままである。
  7. 再びアカウントを追加する。今回はマスターパスワードを追加したので成功する。
  8. アカウントを確認する。ここでは(何故か)4つのアカウントが追加された。最後のアカウントにのみ情報が入っている。
    Expected 0, received 0...>>> PASS <<<
    Name = IRC
   Login = jellybean
     URL = n/a
    Expected 0, received 0...>>> PASS <<<
  1. vaultのロックとアンロックを試行する。すると(これもなぜか)1つのアカウントが生き残る。上記のアカウントだ。

ここまでが、アカウントの作成テスト。

RunExistingVault

まずこのファイルの実行でFailしてしまうのだが、reference.vltを参照仕様として失敗している。これはサンプルプログラムのsample vaultというディレクトリに入っているので、C:\Users\msyksphinz\Documents\reference.vltに移動して実行してみる。

再び実行してみると、最後まで実行されてPassしたようだ。

まずはreference.vltだ。これは暗号化されている。これをどのようにしてテストするか、というところだが、

  1. 既存のreference.vltに対して、さらに新しいvaultファイルを作成する。
  2. スターパスワードを作成し、vaultのパスワードを更新する。
  3. アンロックせずにアカウント情報を読み込む。これはNoPermissionによりエラーが発生すr。
  4. アンロックせずにアカウントのパスワードを読み込む。これはNoPermissionによりエラーが発生すr。
  5. 間違ったパスワードでアンロックする。これはエラーとなる。
  6. 正しいパスワードでアンロックする。これは成功する。
  7. スターパスワードを設定する。
  8. パスワードやアカウントの情報などをいろいろ変更する。変更しても問題ないことを確認する。
f:id:msyksphinz:20180828001205p:plain
=========================================================
EXISTING VAULT TESTS
=========================================================
Checking for reference vault C:\Users\msyksphinz\Documents\reference.vlt
    Expected True, received True...>>> PASS <<<
Backing up original vault file C:\Users\msyksphinz\Documents\reference.vlt to C:\Users\msyksphinz\Documents\reference_orig.vlt
Create new vault on top of existing vault C:\Users\msyksphinz\Documents\reference.vlt
    Expected 5, received 5...>>> PASS <<<
Opening vault C:\Users\msyksphinz\Documents\reference.vlt
    Expected 0, received 0...>>> PASS <<<
Generate password
    Expected 0, received 0...>>> PASS <<<
Password: 3dxy6u6gTAiH5lbx
Set master password
    Expected 6, received 6...>>> PASS <<<
Change master password
    Expected 6, received 6...>>> PASS <<<
Read accounts without unlocking
    Expected 6, received 6...>>> PASS <<<
Read account password without unlocking
    Expected 6, received 6...>>> PASS <<<
Read account without unlocking
    Expected 6, received 6...>>> PASS <<<
Update account without unlocking
    Expected 6, received 6...>>> PASS <<<
Unlock with wrong password
    Expected 13, received 13...>>> PASS <<<
Unlock vault
    Expected 0, received 0...>>> PASS <<<
Set master password
    Expected 8, received 8...>>> PASS <<<
Change master password to itself
    Expected 1, received 1...>>> PASS <<<
Read accounts
    Expected 0, received 0...>>> PASS <<<
3 accounts
    Expected 3, received 3...>>> PASS <<<
Account 0:
    Expected 0, received 0...>>> PASS <<<
    Name = Google
   Login = johnm
     URL = http://google.com/
    Expected 0, received 0...>>> PASS <<<
Password = addition pack solar ring
Account 1:
    Expected 0, received 0...>>> PASS <<<
    Name = Intel
   Login = mechalas
     URL = http://intel.com/
    Expected 0, received 0...>>> PASS <<<
Password = GLV2TE@#P+FvMC?B9wYBz5rj
Account 2:
    Expected 0, received 0...>>> PASS <<<
    Name = Microsoft
   Login = nobody
     URL = http://miscrosoft.com/
    Expected 0, received 0...>>> PASS <<<
Password = O1d-Tongue 0pportunity-ball
Generating new password for account 0
    Expected 0, received 0...>>> PASS <<<
Password 0: #AnzRj4Daqerg11V
Changing account password for account 0
    Expected 0, received 0...>>> PASS <<<
Getting new password for account 0
    Expected 0, received 0...>>> PASS <<<
New password = #AnzRj4Daqerg11V
Comparing generated password #AnzRj4Daqerg11V to assigned password #AnzRj4Daqerg11V
    Expected True, received True...>>> PASS <<<
Generating new password for account 1
    Expected 0, received 0...>>> PASS <<<
Password 1: WfW7@q7o8x@@zQ*x
Changing account password for account 1
    Expected 0, received 0...>>> PASS <<<
Getting new password for account 1
    Expected 0, received 0...>>> PASS <<<
New password = WfW7@q7o8x@@zQ*x
Comparing generated password WfW7@q7o8x@@zQ*x to assigned password WfW7@q7o8x@@zQ*x
    Expected True, received True...>>> PASS <<<
Generating new password for account 2
    Expected 0, received 0...>>> PASS <<<
Password 2: cqYyZc7rWC$FV!yd
Changing account password for account 2
    Expected 0, received 0...>>> PASS <<<
Getting new password for account 2
    Expected 0, received 0...>>> PASS <<<
New password = cqYyZc7rWC$FV!yd
Comparing generated password cqYyZc7rWC$FV!yd to assigned password cqYyZc7rWC$FV!yd
    Expected True, received True...>>> PASS <<<
Fetching undefined account 5:
    Expected 0, received 0...>>> PASS <<<
    Name =
   Login =
     URL =
Fetch password for account 5 to clipboard
    Expected 0, received 0...>>> PASS <<<
Password =
Comparing empty password to undefined account password
    Expected True, received True...>>> PASS <<<
Copy password for account 5 to clipboard
    Expected 0, received 0...>>> PASS <<<
Copy password for account 105 to clipboard
    Expected 4, received 4...>>> PASS <<<
Copy password for account 1 to clipboard
    Expected 0, received 0...>>> PASS <<<
Copy password for account 2 to clipboard
    Expected 0, received 0...>>> PASS <<<
Write new account information for account 2
    Expected 0, received 0...>>> PASS <<<
Get new account information for account 2:
    Expected 0, received 0...>>> PASS <<<
    Name = AOL (should be AOL)
    Expected True, received True...>>> PASS <<<
   Login = aoluser (should be aoluser)
    Expected True, received True...>>> PASS <<<
     URL = http://aol.com/ (should be http://aol.com/)
    Expected True, received True...>>> PASS <<<
Write new account information for account 6
    Expected 0, received 0...>>> PASS <<<
Get new account information for account 6:
    Expected 0, received 0...>>> PASS <<<
    Name = ≪ταБЬ?σ≫ (should be ≪ταБЬ?σ≫)
    Expected True, received True...>>> PASS <<<
   Login =  (should be )
    Expected True, received True...>>> PASS <<<
     URL = http://unicodetest.net/ (should be http://unicodetest.net/)
    Expected True, received True...>>> PASS <<<
Change master password
    Expected 0, received 0...>>> PASS <<<
Lock the vault
    Expected 0, received 0...>>> PASS <<<
Read accounts  after locking
    Expected 6, received 6...>>> PASS <<<
Read account password after locking
    Expected 6, received 6...>>> PASS <<<
Unlock vault with old passphrase
    Expected 13, received 13...>>> PASS <<<
Unlock vault with new passphrase
    Expected 0, received 0...>>> PASS <<<
Read accounts
    Expected 0, received 0...>>> PASS <<<
4 accounts
    Expected 4, received 4...>>> PASS <<<
Account 0:
    Expected 0, received 0...>>> PASS <<<
    Name = Google
   Login = johnm
     URL = http://google.com/
    Expected 0, received 0...>>> PASS <<<
Password = #AnzRj4Daqerg11V
Account 1:
    Expected 0, received 0...>>> PASS <<<
    Name = Intel
   Login = mechalas
     URL = http://intel.com/
    Expected 0, received 0...>>> PASS <<<
Password = WfW7@q7o8x@@zQ*x
Account 2:
    Expected 0, received 0...>>> PASS <<<
    Name = AOL
   Login = aoluser
     URL = http://aol.com/
    Expected 0, received 0...>>> PASS <<<
Password = cqYyZc7rWC$FV!yd
Account 3:
    Expected 0, received 0...>>> PASS <<<
    Name = ≪ταБЬ?σ≫
   Login =
     URL = http://unicodetest.net/
    Expected 0, received 0...>>> PASS <<<
Password =
Copying modified vault to C:\Users\msyksphinz\Documents\reference_modified.vlt
Restoring original vault file from C:\Users\msyksphinz\Documents\reference_orig.vlt to C:\Users\msyksphinz\Documents\reference.vlt
Sleeping for 15 seconds to let clipboard timers finish...
Hit ENTER to exit...

vaultはどこに?

vaultクラスは結局PasswordManagerCoreNativeクラス内のvaultメンバとして定義されているのだが、

  • PasswordManagerCoreaNative.h
 Vault vault;

結局はキーを格納しているクラスにすぎない。

  • PasswordManagerCore.h
class PASSWORDMANAGERCORE_API Vault
{
    Crypto crypto;
    char m_pw_salt[8];
    char db_key_nonce[12];
    char db_key_tag[16];
    char db_key_enc[16];
    char db_key_obs[16];
    char db_key_xor[16];
    UINT16 db_version;
    UINT32 db_size; // Use get_db_size() to fetch this value so it gets updated as needed
    char db_data_nonce[12];
    char db_data_tag[16];
    char *db_data;
...

lock()unlock()はCryptoクラスにより制御されている。

int Vault::unlock(const char *password)
{
    crypto_status_t rv;
    char db_key[16];

    if (!this->is_valid()) return NL_STATUS_INVALID;
    if (!this->is_locked()) return NL_STATUS_OK;

    // Validate the passphrase by attempting to decrypt the database key

    rv = crypto.unlock_vault((PBYTE)password, (ULONG) strlen(password), (PBYTE)m_pw_salt, (PBYTE)db_key_enc, (PBYTE) db_key_nonce, 
        (PBYTE) db_key_tag, (PBYTE) db_key);

    if (rv == CRYPTO_ERR_DECRYPT_AUTH) return NL_STATUS_PASSWORD;
...