Intel SGX Tutorialを読み進めているのだが、サンプルプログラムにも触れておきたい。
まずはPart-3のサンプルコードから。いわゆる普通のソフトウェアとか、GUIのソフトウェアとか触る機会がないので扱い方に少し戸惑うが...
ページの一番最後にダウンロードのリンクがあるのでそれを経由してダウンロードする。
Visual Studio 2017で開いた。メインプログラムはC#で記述されている。
実行するとこのようになる。CUIのプログラムなのでテキストがパラパラと出てきて終了である。 が、最後FAILと表示されているじゃないか。何だこりゃ。
========================================================= 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
- テスト用のvaultを作成する。
- vaultをアンロックする。
- ランダムなパスワードを作成する。
- パスワードなしでアカウントを追加する。これは失敗するはずである。
- マスターパスワードを設定する。マスターパスワードは3.とは異なる。ここでは"12345@#$%asdfg"としている。
- アカウント数を確認する。ここでは4.で失敗したので0のままである。
- 再びアカウントを追加する。今回はマスターパスワードを追加したので成功する。
- アカウントを確認する。ここでは(何故か)4つのアカウントが追加された。最後のアカウントにのみ情報が入っている。
Expected 0, received 0...>>> PASS <<< Name = IRC Login = jellybean URL = n/a Expected 0, received 0...>>> PASS <<<
- vaultのロックとアンロックを試行する。すると(これもなぜか)1つのアカウントが生き残る。上記のアカウントだ。
ここまでが、アカウントの作成テスト。
RunExistingVault
まずこのファイルの実行でFailしてしまうのだが、reference.vlt
を参照仕様として失敗している。これはサンプルプログラムのsample vault
というディレクトリに入っているので、C:\Users\msyksphinz\Documents\reference.vlt
に移動して実行してみる。
再び実行してみると、最後まで実行されてPassしたようだ。
まずはreference.vlt
だ。これは暗号化されている。これをどのようにしてテストするか、というところだが、
- 既存の
reference.vlt
に対して、さらに新しいvaultファイルを作成する。 - マスターパスワードを作成し、vaultのパスワードを更新する。
- アンロックせずにアカウント情報を読み込む。これは
NoPermission
によりエラーが発生すr。 - アンロックせずにアカウントのパスワードを読み込む。これは
NoPermission
によりエラーが発生すr。 - 間違ったパスワードでアンロックする。これはエラーとなる。
- 正しいパスワードでアンロックする。これは成功する。
- マスターパスワードを設定する。
- パスワードやアカウントの情報などをいろいろ変更する。変更しても問題ないことを確認する。
========================================================= 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; ...