Intel SGX Tutorialを読み進めているのだが、サンプルプログラムにも触れておきたい。
まずはPart-3のサンプルコードから。いわゆる普通のソフトウェアとか、GUIのソフトウェアとか触る機会がないので扱い方に少し戸惑うが...
software.intel.com
ページの一番最後にダウンロードのリンクがあるのでそれを経由してダウンロードする。
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...
何をしているのか
public bool RunAll()
{
try {
this.Initialize();
this.RunNewVault();
this.RunExistingVault();
}
catch {
return false;
}
}
mgr.vault_create
によりパスワード管理クラス(PasswordManagerCore
)を作成しているらしい。
PasswordManagerCore mgr;
...
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;
結局はキーを格納しているクラスにすぎない。
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;
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;
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;
...