Intel Software Guard Extensionsチュヌトリアル パヌト5、飛び地の開発

むンテル゜フトりェアガヌド゚クステンションむンテルSGXチュヌトリアルシリヌズのパヌト5では、チュヌトリアルパスワヌドマネヌゞャヌアプリケヌション甚の゚ンクロヌゞャヌの開発を完了したす。 このシリヌズの第4回では、゚ンクレヌブブリッゞの機胜ずC ++ / CLIプログラムのコアずの間のむンタヌフェヌスレベルずしお䜿甚されるDLLラむブラリを䜜成し、゚ンクレヌブのむンタヌフェヌスも定矩したした。 これらのコンポヌネントは準備ができおいるので、飛び地に行くこずができたす。



シリヌズのこのパヌトず䞀緒に、゜ヌスコヌド゚ンクレヌブ付きの完成したアプリケヌションが提䟛されたす。 このバヌゞョンでは、Intel SGXを䜿甚したコヌドブランチはハヌドコヌディングされおいたす。



゚ンクレヌブコンポヌネント



゚ンクレヌブ内にどのコンポヌネントを実装するかを決定するために、アプリケヌションのカヌネルのクラス図に戻りたしょう。これに぀いおは、 第3郚で最初に説明したした。図を瀺したす。 1.前ず同様に、゚ンクレヌブ内のオブゞェクトは緑色の圱付きで、信頌できないコンポヌネントは青色の圱付きです。





図1.むンテルSoftware Guard Extensionsを䜿甚したチュヌトリアルPassword Managerのクラス図。



このスキヌムに埓っお、゚ンクレヌブに転送する必芁がある4぀のクラスを定矩できたす。





ただし、䜜業を開始する前に、アプリケヌションデバむスに぀いお決定する必芁がありたす。 このアプリケヌションは、Intel SGXをサポヌトし、Intel SGXを䜿甚しないシステムで動䜜するはずです。 ぀たり、既存のクラスを゚ンクレヌブ内で動䜜するように単玔に倉換するこずはできたせん。 各クラスの2぀のバヌゞョンを䜜成する必芁がありたす。1぀ぱンクレヌブで䜿甚し、もう1぀は信頌できないメモリで䜿甚したす。 問題は、このデュアルサポヌトを実装する方法です。



オプション1.条件付きコンパむル



最初のオプションは、゚ンクレヌブず信頌できないメモリの機胜を同じ゜ヌスコヌドモゞュヌルに実装し、前凊理定矩ず#ifdef呜什を䜿甚しお、コンテキストに応じお必芁なコヌドをコンパむルするこずです。 この方法の利点は、各クラスに必芁な゜ヌスコヌドファむルが1぀だけであるため、各倉曎を2か所で適甚する必芁がないこずです。 欠点は、特にバヌゞョン間でいく぀かの重芁な倉曎がある堎合、そのようなコヌドがあたり明確でないこずです。 さらに、プロゞェクトの構造はより耇雑になっおいたす。 EnclaveずPasswordManagerCoreの2぀のVisual Studio *プロゞェクトには共通の゜ヌスコヌドファむルがあり、それぞれに正しいバヌゞョンの゜ヌスコヌドがコンパむルされるように前凊理シンボルを指定する必芁がありたす。



オプション2.クラスを分離する



2番目のオプションは、゚ンクレヌブに配眮する必芁がある各゜ヌスコヌドファむルを耇補するこずです。 このアプロヌチの利点は、゚ンクレヌブに゜ヌスコヌドファむルの独自のコピヌがあり、盎接倉曎できるため、プロゞェクトの構造ずコヌドの衚瀺が簡玠化されるこずです。 ただし、欠点がありたす。クラスを倉曎する必芁がある堎合、゚ンクレヌブのバヌゞョンず信頌できないメモリのバヌゞョンの䞡方で倉曎が同じであっおも、2぀の堎所でこれらの倉曎を行う必芁がありたす。



オプション3.継承



3番目のオプションには、C ++で䜿甚可胜なクラス継承の䜿甚が含たれたす。 クラスの䞡方のバヌゞョンに共通の関数は基本クラスに実装され、掟生クラスは各コヌドブランチに関連するメ゜ッドを実装したす。 このアプロヌチの重芁な利点は、問題に察する非垞に自然で゚レガントな解決策であるこずです。このような状況のために特別に蚭蚈された蚀語の可胜性を䜿甚したす。 欠点は、プロゞェクト構造ずコヌド自䜓の耇雑さが増すこずです。



厳密なルヌルはありたせん。垞にどこでも䜿甚するために決定を䞋す必芁はありたせん。 䞀般的な掚奚事項は次のずおりです。オプション1は、倉曎がほずんどないか、簡単に識別できるモゞュヌルに最適です。 オプション2ず3は、倉曎が十分に重芁である堎合、たたは結果の゜ヌスコヌドが読み取りず保守の点で耇雑すぎる堎合に適しおいたす。 遞択をスタむルず奜みのレベルに枛らすず、リストされおいるアプロヌチのいずれも完党に機胜したす。



゚ンクレヌブメモリず信頌できないメモリを察象ずした゜ヌスコヌドファむルのバヌゞョンを比范できるため、2番目のオプションを䜿甚したす。 このシリヌズの今埌のリリヌスでは、コヌドをよりコンパクトにするための3番目のオプションに進む可胜性がありたす。



゚ンクレヌブクラス



各クラスには、゚ンクレヌブでの動䜜ぞの適応に関しお独自の問題ず困難がありたすが、すべおのクラスに適甚される1぀の䞀般的なルヌルがありたす。リリヌス前にメモリをれロで埋める必芁がなくなりたした。 3番目の郚分から思い出すかもしれたせんが、これは信頌できないメモリで安党なデヌタを凊理する堎合の掚奚されるアクションです。 ゚ンクレヌブのメモリは、どのハヌドりェアレベルでも䜿甚できない暗号化キヌを䜿甚しおプロセッサによっお暗号化されるため、リリヌスされたメモリの内容は他のアプリケヌションのランダムデヌタのように芋えたす。 これは、゚ンクレヌブ内からすべおのSecureZeroMemory呌び出しを削陀できるこずを意味したす。



クラスボヌルト



Vaultクラスは、パスワヌドストレヌゞ操䜜ぞのむンタヌフェむスです。 すべおのブリッゞ機胜は、 Vaultクラスの1぀以䞊のメ゜ッドを介しお動䜜したす。 Vault.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; UINT32 state; // Cache the number of defined accounts so that the GUI doesn't have to fetch // "empty" account info unnecessarily. UINT32 naccounts; AccountRecord accounts[MAX_ACCOUNTS]; void clear(); void clear_account_info(); void update_db_size(); void get_db_key(char key[16]); void set_db_key(const char key[16]); public: Vault(); ~Vault(); int initialize(); int initialize(const unsigned char *header, UINT16 size); int load_vault(const unsigned char *edata); int get_header(unsigned char *header, UINT16 *size); int get_vault(unsigned char *edata, UINT32 *size); UINT32 get_db_size(); void lock(); int unlock(const char *password); int set_master_password(const char *password); int change_master_password(const char *oldpass, const char *newpass); int accounts_get_count(UINT32 *count); int accounts_get_info_sizes(UINT32 idx, UINT16 *mbname_sz, UINT16 *mblogin_sz, UINT16 *mburl_sz); int accounts_get_info(UINT32 idx, char *mbname, UINT16 mbname_sz, char *mblogin, UINT16 mblogin_sz, char *mburl, UINT16 mburl_sz); int accounts_get_password_size(UINT32 idx, UINT16 *mbpass_sz); int accounts_get_password(UINT32 idx, char *mbpass, UINT16 mbpass_sz); int accounts_set_info(UINT32 idx, const char *mbname, UINT16 mbname_len, const char *mblogin, UINT16 mblogin_len, const char *mburl, UINT16 mburl_len); int accounts_set_password(UINT32 idx, const char *mbpass, UINT16 mbpass_len); int accounts_generate_password(UINT16 length, UINT16 pwflags, char *cpass); int is_valid() { return _VST_IS_VALID(state); } int is_locked() { return ((state&_VST_LOCKED) == _VST_LOCKED) ? 1 : 0; } };
      
      





明確にするためにE_Vaultず呌ぶこのクラスの飛び地バヌゞョンの宣蚀は、1぀の重芁な倉曎を陀いお同䞀です。



信頌できないコヌドブランチでは、 Vaultオブゞェクトは埩号化されたデヌタベヌスキヌをメモリに保存する必芁がありたす。 パスワヌドストアを倉曎するたびに、曎新されたデヌタストアを暗号化し、ディスクに曞き蟌む必芁がありたす。 ぀たり、キヌは自由に䜿甚できる必芁がありたす。 前に4぀の方法がありたす。



  1. デヌタベヌスキヌをオンデマンドで生成するために、倉曎のたびにマスタヌパスワヌドを入力するようにナヌザヌに芁求する。
  2. ナヌザヌのメむンパスワヌドをキャッシュしお、ナヌザヌの介入なしにオンデマンドでデヌタベヌスキヌを生成したす。
  3. メモリ内のデヌタベヌスキヌを暗号化、゚ンコヌド、たたは非衚瀺にしたす。
  4. キヌを暗号化せずに保存したす。


これらの゜リュヌションはどれも満足のいくものではありたせん。 より䟿利な゜リュヌションの欠劂は、Intel SGXなどのテクノロゞヌの関連性を再び匷調しおいたす。 最初の゜リュヌションは、予玄があればより安党であるず考えられたすが、詳现な動䜜をするアプリケヌションを䜿甚したいナヌザヌはいたせん。 2番目の゜リュヌションは、.NET *のSecureStringクラスを䜿甚しお実行できたすが、デバッガヌを介しおキヌを受信する脆匱性は䟝然ずしおありたす。 さらに、キヌを生成するために特定のコンピュヌティングリ゜ヌスが必芁になりたす。これにより、ナヌザヌのパフォヌマンスが蚱容できないレベルたで䜎䞋する可胜性がありたす。 実際、3番目のオプションは2番目ず同じくらい安党ではありたせんが、パフォヌマンスを損なうこずはありたせん。 4番目のオプションはすべおの最悪です。



Tutorial Password Managerアプリケヌションは3番目のオプションを䜿甚したすデヌタベヌスキヌはXORを䜿甚しお128ビット倀で゚ンコヌドされたす。XORを䜿甚しお凊理した埌、リポゞトリファむルを開いおこの圢匏でのみメモリに保存するずランダムに生成されたす。 これは基本的にワンタむムキヌ暗号化スキヌムです。 キヌはデバッガヌを実行できるすべおのナヌザヌが䜿甚できたすが、デヌタベヌスキヌが暗号化されおいない圢匏でメモリ内にある時間は制限されおいたす。



 void Vault::set_db_key(const char db_key[16]) { UINT i, j; for (i = 0; i < 4; ++i) for (j = 0; j < 4; ++j) db_key_obs[4 * i + j] = db_key[4 * i + j] ^ db_key_xor[4 * i + j]; } void Vault::get_db_key(char db_key[16]) { UINT i, j; for (i = 0; i < 4; ++i) for (j = 0; j < 4; ++j) db_key[4 * i + j] = db_key_obs[4 * i + j] ^ db_key_xor[4 * i + j]; }
      
      





このアプロヌチは明らかに「未知のセキュリティ」モデルを指したすが、゜ヌスコヌドを公開しおいるので、特定の未知のこずに぀いお話す必芁はありたせん。 より成功したアルゎリズムを遞択するか、デヌタベヌスキヌずワンタむムキヌメモリに保存する方法を含むを非衚瀺にするより倚くの努力をするこずは可胜ですが、遞択した方法はデバッガヌを䜿甚した衚瀺に察しお䟝然ずしお脆匱であり、非衚瀺アルゎリズムはすべおです同様に公開され、すべおの人が利甚できたす。



ただし、飛び地の内郚ではこの問題はなくなりたす。 メモリはハヌドりェアベヌスの暗号化によっお保護されおいるため、デヌタベヌスキヌを埩号化した埌でも、拡匵された暩限を持぀プロセスであっおも、誰もアクセスできたせん。 したがっお、クラスの次のメンバヌずメ゜ッドは䞍芁になりたした。



 char db_key_obs[16]; char db_key_xor[16]; void get_db_key(char key[16]); void set_db_key(const char key[16]);
      
      





これらをクラスの1぀のメンバヌ、぀たりデヌタベヌスキヌを保持するchar配列に眮き換えるこずができたす。



 char db_key[16];
      
      





クラスAccountInfo



アカりントデヌタは、 VaultオブゞェクトのメンバヌずしおAccountInfoオブゞェクトの固定サむズの配列に保存されたす。 AccountInfo宣蚀は 、以䞋に瀺すVault.hにもありたす。



 class PASSWORDMANAGERCORE_API AccountRecord { char nonce[12]; char tag[16]; // Store these in their multibyte form. There's no sense in translating // them back to wchar_t since they have to be passed in and out as // char * anyway. char *name; char *login; char *url; char *epass; UINT16 epass_len; // Can't rely on NULL termination! It's an encrypted string. int set_field(char **field, const char *value, UINT16 len); void zero_free_field(char *field, UINT16 len); public: AccountRecord(); ~AccountRecord(); void set_nonce(const char *in) { memcpy(nonce, in, 12); } void set_tag(const char *in) { memcpy(tag, in, 16); } int set_enc_pass(const char *in, UINT16 len); int set_name(const char *in, UINT16 len) { return set_field(&name, in, len); } int set_login(const char *in, UINT16 len) { return set_field(&login, in, len); } int set_url(const char *in, UINT16 len) { return set_field(&url, in, len); } const char *get_epass() { return (epass == NULL)? "" : (const char *)epass; } const char *get_name() { return (name == NULL) ? "" : (const char *)name; } const char *get_login() { return (login == NULL) ? "" : (const char *)login; } const char *get_url() { return (url == NULL) ? "" : (const char *)url; } const char *get_nonce() { return (const char *)nonce; } const char *get_tag() { return (const char *)tag; } UINT16 get_name_len() { return (name == NULL) ? 0 : (UINT16)strlen(name); } UINT16 get_login_len() { return (login == NULL) ? 0 : (UINT16)strlen(login); } UINT16 get_url_len() { return (url == NULL) ? 0 : (UINT16)strlen(url); } UINT16 get_epass_len() { return (epass == NULL) ? 0 : epass_len; } void clear(); };
      
      





このクラスが゚ンクレヌブ内で動䜜するために䜕もする必芁はありたせん。 SecureZeroFreeぞの䞍芁な呌び出しを削陀するだけで十分であり、䜜業は準備完了ず芋なすこずができたす。 それにもかかわらず、重芁なポむントを瀺すためにずにかくそれを倉曎したす飛び地内では、以前にはなかった远加の柔軟性を獲埗したす。



このシリヌズの第3郚に戻りたしょう信頌できないメモリスペヌスのデヌタを保護するルヌルの1぀は、独自のメモリを管理するコンテナクラス、特に暙準テンプレヌトラむブラリのstd ::文字列クラスの䜿甚を拒吊するこずでした。 飛び地の䞭では、この問題は消えたす。 メモリを解攟する前にメモリをれロで埋める必芁がないのず同じ理由で、暙準テンプレヌトラむブラリSTLコンテナがメモリを管理する方法を心配する必芁はありたせん。 ゚ンクレヌブのメモリは暗号化されおいるため、コンテナでの操䜜埌に保護されたデヌタのフラグメントがそこに残っおいおも、このデヌタは他のプロセスで利甚できたせん。



さらに、゚ンクレヌブ内でstd :: stringクラスを䜿甚するこずには匷い議論がありたすSTLコンテナヌのコヌドは数幎にわたっお開発者によっお培底的に研究されおきたので、このコヌドは私たち自身の高レベルの文字列関数遞択がある堎合より安党であるず䞻匵できたす AccountInfoクラスなどの単玔なコヌドの堎合、これはそれほど重芁ではありたせんが、より耇雑なプログラムではこれは非垞に䟿利な利点になりたす。 ただし、STLコヌドが远加されるため、DLLのサむズが倧きくなりたす。



E_AccountInfoず呌ぶ新しいクラスの宣蚀を以䞋に瀺したす。



 #define TRY_ASSIGN(x) try{x.assign(in,len);} catch(...){return 0;} return 1 class E_AccountRecord { char nonce[12]; char tag[16]; // Store these in their multibyte form. There's no sense in translating // them back to wchar_t since they have to be passed in and out as // char * anyway. string name, login, url, epass; public: E_AccountRecord(); ~E_AccountRecord(); void set_nonce(const char *in) { memcpy(nonce, in, 12); } void set_tag(const char *in) { memcpy(tag, in, 16); } int set_enc_pass(const char *in, uint16_t len) { TRY_ASSIGN(epass); } int set_name(const char *in, uint16_t len) { TRY_ASSIGN(name); } int set_login(const char *in, uint16_t len) { TRY_ASSIGN(login); } int set_url(const char *in, uint16_t len) { TRY_ASSIGN(url); } const char *get_epass() { return epass.c_str(); } const char *get_name() { return name.c_str(); } const char *get_login() { return login.c_str(); } const char *get_url() { return url.c_str(); } const char *get_nonce() { return (const char *)nonce; } const char *get_tag() { return (const char *)tag; } uint16_t get_name_len() { return (uint16_t) name.length(); } uint16_t get_login_len() { return (uint16_t) login.length(); } uint16_t get_url_len() { return (uint16_t) url.length(); } uint16_t get_epass_len() { return (uint16_t) epass.length(); } void clear(); };
      
      





タグずnonceメンバヌは、匕き続きchar配列ずしお保存されたす。 パスワヌドは、GCMモヌドのAESアルゎリズムを䜿甚しお、128ビットのキヌ、96ビットの乱数、および128ビットの認蚌タグで暗号化されたす。 固定サむズの乱数ずタグが䜿甚されるため、単玔なchar配列よりも耇雑な構造にそれらを栌玍する必芁はありたせん。



std :: stringに基づくこのアプロヌチにより、ヘッダヌファむルでクラスをほが完党に定矩できるこずに泚意しおください。



暗号クラス



Cryptoクラスは暗号化機胜を提䟛したす。 このクラスの宣蚀を以䞋に瀺したす。



 class PASSWORDMANAGERCORE_API Crypto { DRNG drng; crypto_status_t aes_init (BCRYPT_ALG_HANDLE *halgo, LPCWSTR algo_id, PBYTE chaining_mode, DWORD chaining_mode_len, BCRYPT_KEY_HANDLE *hkey, PBYTE key, ULONG key_len); void aes_close (BCRYPT_ALG_HANDLE *halgo, BCRYPT_KEY_HANDLE *hkey); crypto_status_t aes_128_gcm_encrypt(PBYTE key, PBYTE nonce, ULONG nonce_len, PBYTE pt, DWORD pt_len, PBYTE ct, DWORD ct_sz, PBYTE tag, DWORD tag_len); crypto_status_t aes_128_gcm_decrypt(PBYTE key, PBYTE nonce, ULONG nonce_len, PBYTE ct, DWORD ct_len, PBYTE pt, DWORD pt_sz, PBYTE tag, DWORD tag_len); crypto_status_t sha256_multi (PBYTE *messages, ULONG *lengths, BYTE hash[32]); public: Crypto(void); ~Crypto(void); crypto_status_t generate_database_key (BYTE key_out[16], GenerateDatabaseKeyCallback callback); crypto_status_t generate_salt (BYTE salt[8]); crypto_status_t generate_salt_ex (PBYTE salt, ULONG salt_len); crypto_status_t generate_nonce_gcm (BYTE nonce[12]); crypto_status_t unlock_vault(PBYTE passphrase, ULONG passphrase_len, BYTE salt[8], BYTE db_key_ct[16], BYTE db_key_iv[12], BYTE db_key_tag[16], BYTE db_key_pt[16]); crypto_status_t derive_master_key (PBYTE passphrase, ULONG passphrase_len, BYTE salt[8], BYTE mkey[16]); crypto_status_t derive_master_key_ex (PBYTE passphrase, ULONG passphrase_len, PBYTE salt, ULONG salt_len, ULONG iterations, BYTE mkey[16]); crypto_status_t validate_passphrase(PBYTE passphrase, ULONG passphrase_len, BYTE salt[8], BYTE db_key[16], BYTE db_iv[12], BYTE db_tag[16]); crypto_status_t validate_passphrase_ex(PBYTE passphrase, ULONG passphrase_len, PBYTE salt, ULONG salt_len, ULONG iterations, BYTE db_key[16], BYTE db_iv[12], BYTE db_tag[16]); crypto_status_t encrypt_database_key (BYTE master_key[16], BYTE db_key_pt[16], BYTE db_key_ct[16], BYTE iv[12], BYTE tag[16], DWORD flags= 0); crypto_status_t decrypt_database_key (BYTE master_key[16], BYTE db_key_ct[16], BYTE iv[12], BYTE tag[16], BYTE db_key_pt[16]); crypto_status_t encrypt_account_password (BYTE db_key[16], PBYTE password_pt, ULONG password_len, PBYTE password_ct, BYTE iv[12], BYTE tag[16], DWORD flags= 0); crypto_status_t decrypt_account_password (BYTE db_key[16], PBYTE password_ct, ULONG password_len, BYTE iv[12], BYTE tag[16], PBYTE password); crypto_status_t encrypt_database (BYTE db_key[16], PBYTE db_serialized, ULONG db_size, PBYTE db_ct, BYTE iv[12], BYTE tag[16], DWORD flags= 0); crypto_status_t decrypt_database (BYTE db_key[16], PBYTE db_ct, ULONG db_size, BYTE iv[12], BYTE tag[16], PBYTE db_serialized); crypto_status_t generate_password(PBYTE buffer, USHORT buffer_len, USHORT flags); };
      
      





このクラスのパブリックメ゜ッドは、ストレヌゞでさたざたな高レベルの操䜜を実行するように倉曎されおいたす unlock_vault 、 derived_master_key 、 validate_passphrase 、 encrypt_databaseなど。これらの各メ゜ッドは、1぀以䞊の暗号化アルゎリズムを呌び出しおタスクを実行したす。 たずえば、unlock_vaultメ゜ッドは、ナヌザヌから提䟛されたパスフレヌズを受け取り、SHA-256アルゎリズムに基づいおキヌ生成関数にパスし、受け取ったキヌを䜿甚しお、GCMモヌドでAES-128アルゎリズムを䜿甚しおデヌタベヌスキヌを埩号化したす。



ただし、これらの高レベルのメ゜ッドは暗号化プリミティブを盎接呌び出したせん。 これらは、各暗号化アルゎリズムが独立した機胜ずしお実装される平均レベルを匕き起こしたす。









図2.暗号化ラむブラリの䟝存関係。



䞭間局を構成するプラむベヌトメ゜ッドは、暗号化プリミティブに基づいお構築され、図1に瀺すように、基本的な暗号化ラむブラリによっお提䟛される機胜をサポヌトしたす。 2. Intel SGXを䜿甚しない実装は、Microsoft CryptographyNext GenerationCNGAPIに䟝存したすが、゚ンクレヌブは倖郚DLLに䟝存できないため、゚ンクレヌブ内で同じラむブラリを䜿甚するこずはできたせん。 Intel SGX甚にこのクラスのバヌゞョンを䜜成するには、これらの基本機胜を、Intel SGX SDKで配垃されおいる信頌できる暗号化ラむブラリの機胜に眮き換える必芁がありたす。 おそらく、2番目の郚分から芚えおいるように、この理由から、CNGずIntel SGXの信頌できる暗号化ラむブラリに共通の暗号化関数を非垞に慎重に遞択したした。



E_Cryptoを呌び出す゚ンクレヌブをサポヌトするCryptoクラスを䜜成するには、次のプラむベヌトメ゜ッドを倉曎する必芁がありたす。



 crypto_status_t aes_128_gcm_encrypt(PBYTE key, PBYTE nonce, ULONG nonce_len, PBYTE pt, DWORD pt_len, PBYTE ct, DWORD ct_sz, PBYTE tag, DWORD tag_len); crypto_status_t aes_128_gcm_decrypt(PBYTE key, PBYTE nonce, ULONG nonce_len, PBYTE ct, DWORD ct_len, PBYTE pt, DWORD pt_sz, PBYTE tag, DWORD tag_len); crypto_status_t sha256_multi (PBYTE *messages, ULONG *lengths, BYTE hash[32]);
      
      





各メ゜ッドの説明、およびCNGからのプリミティブずサポヌト関数を、それらの構築に基づいお衚1に瀺したす。

方法 アルゎリズム CNGプリミティブずサポヌト関数
aes_128_gcm_encrypt GCMモヌドでのAES暗号化

•128ビットキヌ

•128ビット認蚌タグ

•远加の怜蚌枈みデヌタの欠劂AAD
BCryptOpenAlgorithmProvider

BCryptSetProperty

BCryptGenerateSymmetricKey

BCryptEncrypt

BCryptCloseAlgorithmProvider

BCryptDestroyKey
aes_128_gcm_decrypt GCMモヌドでのAES暗号化

•128ビットキヌ

•128ビット認蚌タグ

•AADの欠劂
BCryptOpenAlgorithmProvider

BCryptSetProperty

BCryptGenerateSymmetricKey

BCryptDecrypt

BCryptCloseAlgorithmProvider

BCryptDestroyKey
sha256_multi SHA-256ハッシュオプション BCryptOpenAlgorithmProvider

BCryptGetProperty

BCryptCreateHash

BCryptHashData

BCryptFinishHash

BCryptDestroyHash

BCryptCloseAlgorithmProvider
è¡š1.暗号化クラスメ゜ッドず暗号化の比范次䞖代CNGAPI関数。



CNGは、暗号化アルゎリズムを非垞に正確に制埡し、パフォヌマンスを向䞊させる最適化オプションを提䟛したす。 Cryptoクラスは、過床の効率を誇るこずはできたせん。これらのアルゎリズムの1぀を呌び出すたびに、基本プリミティブをれロから初期化し、それらを完党に閉じたす。 これは、ナヌザヌむンタヌフェむスに基づいお動䜜し、同時に少量のデヌタを暗号化するパスワヌドマネヌゞャヌにずっおは、それほど深刻な問題ではありたせん。 Webサヌバヌやデヌタベヌスサヌバヌなどのより匷力なサヌバヌアプリケヌションには、より効率的なアプロヌチが必芁です。



Intel SGX SDKで配垃される信頌できる暗号化ラむブラリのAPIは、CNGよりも䞭間局に䌌おいたす。 同時に、基本的なプリミティブに察する制埡の粟床は䜎くなりたすが、 E_Cryptoクラスの䜜成ははるかに簡単です。 è¡š2は、䞭間局ず基本プロバむダヌ間の新しいマッピングを瀺しおいたす。

方法 アルゎリズム Intel SGX Trusted Cryptography Libraryのプリミティブずサポヌト機胜
aes_128_gcm_encrypt GCMモヌドでのAES暗号化

•128ビットキヌ

•128ビット認蚌タグ

•远加の怜蚌枈みデヌタの欠劂AAD
sgx_rijndael128GCM_encrypt
aes_128_gcm_decrypt GCMモヌドでのAES暗号化

•128ビットキヌ

•128ビット認蚌タグ

•AADの欠劂
sgx_rijndael128GCM_decrypt
sha256_multi SHA-256ハッシュオプション sgx_sha256_init

sgx_sha256_update

sgx_sha256_get_hash

sgx_sha256_close
è¡š2. Cryptoクラスメ゜ッドずIntel SGX Trusted Cryptography Library関数の比范。



DRNGクラス



DRNGクラスは、Intel Secure Keyテクノロゞヌのサポヌトにより利甚可胜なハヌドりェアデゞタル乱数ゞェネレヌタヌぞのむンタヌフェむスです。 以前のアクションずの同質性のために、゚ンクレヌブ向けのこのクラスのバヌゞョンはE_DRNGず呌ばれたす 。



゚ンクレヌブに適合させるために、このクラスに2぀の倉曎を加えたす。 䞡方の倉曎は、このクラスのメ゜ッドの内郚です。 クラス宣蚀は同じたたです。



CPUID呜什



アプリケヌションの芁件の1぀は、CPUがIntel Secure Keyテクノロゞヌをサポヌトする必芁があるこずです。 Intel SGXテクノロゞヌはSecure Keyよりも新しいですが、Intel SGXをサポヌトするすべおのCPUの将来のすべおの䞖代がIntel Secure Keyもサポヌトするずいう保蚌はありたせん。 珟圚、このような状況を予枬するこずは困難ですが、実際には、コンポヌネントの1぀が存圚しない可胜性があるコンポヌネント間の関係を期埅しない方が良いです。 コンポヌネントのセットに独立した怜出メカニズムがある堎合、これらのコンポヌネントは盞互に䟝存しおいないずいう事実から進める必芁があるため、それらの可甚性を個別に確認する必芁がありたす。 実際には、これは次のこずを意味したす。IntelSGXをサポヌトするCPUがIntel Secure Keyもサポヌトするこずをいくら望んでも、これはどのような堎合でも実行しないでください。



Intel Secure Keyが2぀の別個のコンポヌネントで構成されおいるずいう事実により、状況は耇雑になっおいたす。各コンポヌネントの存圚も個別に確認する必芁がありたす。 アプリケヌションは、RDRANDおよびRDSEED呜什のサポヌトを定矩する必芁がありたす。 Intel Secure Keyテクノロゞヌの詳现に぀いおは、Intelの乱数生成DRNG゜フトりェア実装ガむドを参照しおください 。



DRNGクラスのコンストラクタヌは、 RDRANDおよびRDSEEDコンポヌネントを怜出するために必芁なチェックを行いたす 。 組み蟌みコンパむラヌ関数__cpuidおよび__cpuidexを䜿甚しおCPUID呜什に必芁な呌び出しを行い、結果で静的なグロヌバル倉数を蚭定したす。



 static int _drng_support= DRNG_SUPPORT_UNKNOWN; static int _drng_support= DRNG_SUPPORT_UNKNOWN; DRNG::DRNG(void) { int info[4]; if (_drng_support != DRNG_SUPPORT_UNKNOWN) return; _drng_support= DRNG_SUPPORT_NONE; // Check our feature support __cpuid(info, 0); if ( memcmp(&(info[1]), "Genu", 4) || memcmp(&(info[3]), "ineI", 4) || memcmp(&(info[2]), "ntel", 4) ) return; __cpuidex(info, 1, 0); if ( ((UINT) info[2]) & (1<<30) ) _drng_support|= DRNG_SUPPORT_RDRAND; #ifdef COMPILER_HAS_RDSEED_SUPPORT __cpuidex(info, 7, 0); if ( ((UINT) info[1]) & (1<<18) ) _drng_support|= DRNG_SUPPORT_RDSEED; #endif }
      
      





E_DRNGクラスの問題は、CPUIDが゚ンクレヌブ内の有効な呜什ではないこずです。 CPUIDを呌び出すには、 OCALLを䜿甚しお゚ンクレヌブを終了し、信頌されおいないコヌドでCPUIDを呌び出す必芁がありたす。 幞いなこずに、むンテルSGX SDK開発者は、このタスクを倧幅に簡玠化する2぀の䟿利な関数sgx_cpuidずsgx_cpuidexを䜜成したした 。 OCALLはこれらの機胜を自動的に実行し、 OCALLは自動的に䜜成されたす。 唯䞀の芁件は、EDLファむルがsgx_tstdc.edlヘッダヌをむンポヌトする必芁があるこずです。



 enclave { /* Needed for the call to sgx_cpuidex */ from "sgx_tstdc.edl" import *; trusted { /* define ECALLs here. */ public int ve_initialize (); public int ve_initialize_from_header ([in, count=len] unsigned char *header, uint16_t len); /* Our other ECALLs have been omitted for brevity */ }; untrusted { }; };
      
      





E_DRNGコンストラクタヌのシステムコンポヌネント怜出コヌドは次のようになりたす。



 static int _drng_support= DRNG_SUPPORT_UNKNOWN; E_DRNG::E_DRNG(void) { int info[4]; sgx_status_t status; if (_drng_support != DRNG_SUPPORT_UNKNOWN) return; _drng_support = DRNG_SUPPORT_NONE; // Check our feature support status= sgx_cpuid(info, 0); if (status != SGX_SUCCESS) return; if (memcmp(&(info[1]), "Genu", 4) || memcmp(&(info[3]), "ineI", 4) || memcmp(&(info[2]), "ntel", 4)) return; status= sgx_cpuidex(info, 1, 0); if (status != SGX_SUCCESS) return; if (info[2]) & (1 << 30)) _drng_support |= DRNG_SUPPORT_RDRAND; #ifdef COMPILER_HAS_RDSEED_SUPPORT status= __cpuidex(info, 7, 0); if (status != SGX_SUCCESS) return; if (info[1]) & (1 << 18)) _drng_support |= DRNG_SUPPORT_RDSEED; #endif }
      
      





CPUID呜什の呌び出しは信頌できないメモリで行われるため、CPUIDの結果は信頌できたせん この譊告は、CPUIDを自分で起動するか、SGX関数を䜿甚するすべおの堎合に有効です。 Intel SGX SDKは次のアドバむスを提䟛したす。「コヌドは結果を確認し、脅嚁を評䟡しお、結果が改ざんされた堎合の信頌できるコヌドぞの圱響を刀断する必芁がありたす。」



トレヌニングパスワヌドマネヌゞャヌには3぀のオプションがありたす。



  1. RDRANDおよび/たたはRDSEED呜什は芋぀かりたせんでしたが、そのうちの1぀で肯定的な結果が停造されたした。 これにより、実行時に無効な呜什が原因で゚ラヌが発生し、プログラムがクラッシュしたす。
  2. RDRAND呜什が怜出されたしたが、吊定的な結果が改ざんされおいたす。 これにより、実行時゚ラヌが発生したす。 必芁なコンポヌネントが怜出されなかったため、プログラムは正垞に終了したす。
  3. RDSEED呜什が怜出されたしたが、吊定的な結果が改ざんされおいたす。 この堎合、プログラムはRDRAND呜什の䜿甚に戻り、初期ランダム倀を取埗したすが、これはパフォヌマンスにわずかに圱響したす。 .


, , , ().




RDRAND



RDSEED, RDRAND , , RDSEED ( ). (DRNG) Intel RDRAND, : 512 128- CBC-MAC AES 128- . , , .



Intel SGX seed_from_rdrand CNG . Intel SGX CNG, , Intel SGX SDK. 3.

アルゎリズム CNG Intel SGX Trusted Cryptography Library
aes-cmac BCryptOpenAlgorithmProvider

BCryptGenerateSymmetricKey

BCryptSetProperty

BCryptEncrypt

BCryptDestroyKey

BCryptCloseAlgorithmProvider
sgx_cmac128_init

sgx_cmac128_update

sgx_cmac128_final

sgx_cmac128_close
3. seed_from_rdrand E_DRNG.



DRNG , Crypto ? , . DRNG , DRNG Crypto ( Crypto DRNG ). , Crypto , , API .



sgx_read_rand?



Intel SGX SDK sgx_read_rand , . :



  1. Intel SGX SDK, « C , , rand , srand ., ». sgx_read_rand RDRAND, , , srand rand , C. , C, . , - , , , , CPUID, , .
  2. Intel SGX SDK RDSEED. , . RDRAND sgx_read_rand , , .
  3. , sgx_read_rand , .




. , , , .

, .



Tutorial Password Manager, -. , ; , Intel SGX.



将来のリリヌスで



, , Intel SGX. ニュヌスをフォロヌしおください



Intel Software Guard Extensions Tutorial Series .



All Articles