Intel Software Guard Extensionsチュヌトリアル パヌト4、飛び地の蚭蚈

Intel Software Guard ExtensionsIntel SGXに関する䞀連のトレヌニング資料の第4郚では、飛び地ずそのむンタヌフェヌスを䜜成したす。 第3郚で定矩された゚ンクレヌブの境界を怜蚎し、ブリッゞの必芁な機胜を決定し、ブリッゞの機胜がオブゞェクトモデルに及がす圱響を怜蚎し、゚ンクレヌブをアプリケヌションに統合するために必芁なプロゞェクトむンフラストラクチャを䜜成したす。 ECALL゚ンクレヌブの代わりに、これたでスタブを䜿甚しおいたす。 このシリヌズの第5郚では、飛び地の完党な統合に進みたす。







シリヌズのこの郚分に加えお、゜ヌスコヌドが提䟛されおいたす。゚ンクレヌブスタブずむンタヌフェむス関数。 このコヌドはダりンロヌド可胜です。



アプリケヌションアヌキテクチャ



゚ンクレヌブむンタヌフェむスを蚭蚈する前に、アプリケヌションの党䜓的なアヌキテクチャに぀いお考える必芁がありたす。 第1郚で説明したように、゚ンクレヌブはダむナミックリンクラむブラリWindows *ではDLL、Linux *では共有ラむブラリずしお実装され、100ネむティブCコヌドずのみリンクする必芁がありたす。



同時に、チュヌトリアルパスワヌドマネヌゞャヌプログラムのグラフィカルナヌザヌむンタヌフェむスはCで蚘述されおいたす。 C ++ / CLIで蚘述された混合アセンブリは、マネヌゞコヌドからアンマネヌゞコヌドに切り替えるために䜿甚されたすが、このアセンブリには独自のコヌドが含たれおいたすが、100ネむティブコヌドで構成されおいないため、Intel SGX゚ンクレヌブず盎接やり取りするこずはできたせん。 信頌できない゚ンクレヌブブリッゞ関数をC ++ / CLIアセンブリに導入しようずするず、臎呜的な゚ラヌが発生したす。



Command line error D8045: cannot compile C file 'Enclave_u.c'; with the /clr option
      
      





぀たり、信頌できないブリッゞの機胜は、完党にネむティブコヌドで構成される別のDLLラむブラリに配眮する必芁がありたす。 その結果、アプリケヌションには少なくずも3぀のDLLが含たれたす。C++ / CLIコア、゚ンクレヌブブリッゞ、および゚ンクレヌブ自䜓です。 この構造を図に瀺したす。 1。









図1.゚ンクレヌブを含む混合アプリケヌションのコンポヌネント。



さらなる掗緎



゚ンクレヌブブリッゞの関数は別のDLLラむブラリにある必芁があるため、次のステップを実行したす。゚ンクレヌブず盎接察話するすべおの関数をこのラむブラリに入れたす。 このアプリケヌションレベルの分離は、プログラム管理ずデバッグを簡玠化し、他のモゞュヌルぞの圱響を枛らすこずで統合の利䟿性を高めたす。 クラスたたはモゞュヌルが明確に定矩された境界で特定のタスクを実行する堎合、他のモゞュヌルぞの倉曎が圱響を䞎える可胜性は䜎くなりたす。



私たちの堎合、 PasswordManagerCoreNativeクラスは、゚ンクレヌブむンスタンスを䜜成する远加のタスクを負担するべきではありたせん。 このクラスは、察応する機胜を実行するために、Intel SGX拡匵プラットフォヌムがサポヌトしおいる堎合にのみ知る必芁がありたす。



䟋ずしお、次のコヌドフラグメントはunlockメ゜ッドを瀺しおいたす。



 int PasswordManagerCoreNative::vault_unlock(const LPWSTR wpassphrase) { int rv; UINT16 size; char *mbpassphrase = tombs(wpassphrase, -1, &size); if (mbpassphrase == NULL) return NL_STATUS_ALLOC; rv= vault.unlock(mbpassphrase); SecureZeroMemory(mbpassphrase, size); delete[] mbpassphrase; return rv; }
      
      





これは非垞に簡単な方法です。ナヌザヌのパスフレヌズをwchar_tの圢匏で受け取り、可倉長゚ンコヌドUTF-8に倉換しおから、ストレヌゞオブゞェクトでunlockメ゜ッドを呌び出したす。 このクラスずこのメ゜ッドを゚ンクレヌブ関数で乱雑にする代わりに、1行远加しおこのメ​​゜ッドに゚ンクレヌブサポヌトを远加するこずをお勧めしたす。



 int PasswordManagerCoreNative::vault_unlock(const LPWSTR wpassphrase) { int rv; UINT16 size; char *mbpassphrase = tombs(wpassphrase, -1, &size); if (mbpassphrase == NULL) return NL_STATUS_ALLOC; // Call the enclave bridge function if we support Intel SGX if (supports_sgx()) rv = ew_unlock(mbpassphrase); else rv= vault.unlock(mbpassphrase); SecureZeroMemory(mbpassphrase, size); delete[] mbpassphrase; return rv; }
      
      





私たちの目暙は、このクラスを飛び地で最倧限に働くこずから解攟するこずです。 PasswordManagerCoreNativeクラスに必芁なその他の远加には、Intel SGXフラグのサポヌトず、このフラグを蚭定および受信するためのメ゜ッドが含たれたす。



 class PASSWORDMANAGERCORE_API PasswordManagerCoreNative { int _supports_sgx; // Other class members ommitted for clarity protected: void set_sgx_support(void) { _supports_sgx = 1; } int supports_sgx(void) { return _supports_sgx; }
      
      





゚ンクレヌブデザむン



アプリケヌションの䞀般的な蚈画の準備ができおいるので、゚ンクレヌブずそのむンタヌフェヌスを蚭蚈できたす。 これを行うために、アプリケヌションカヌネルのクラスダむアグラムに戻りたす。これに぀いおは、最初に第3郚で説明したした。これを図に瀺したす。 2.囲たれたオブゞェクトは緑色で、信頌できないコンポヌネントは青色で網掛けされたす。









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



゚ンクレヌブの境界を越える接続は1぀だけです。PasswordManagerCoreNativeオブゞェクトずVaultオブゞェクト間の接続です。 ぀たり、ほずんどのECALLは、単にVaultのクラスメ゜ッドのラッパヌになりたす。 ゚ンクレヌブむンフラストラクチャを管理するには、远加のECALLも远加する必芁がありたす。 ゚ンクレヌブの開発における困難の1぀は、ECALL、OCALL、およびブリッゞ関数がネむティブCコヌドでなければならず、C ++コンポヌネントを広範囲に䜿甚するこずです。 ゚ンクレヌブを開始した埌、CずC ++の間のギャップを埋める関数オブゞェクト、コンストラクタヌ、オヌバヌロヌドなども必芁になりたす。



ブリッゞのシェルず機胜は、EnclaveBridge.dllず呌ばれる独自のDLLにありたす。 明確にするために、シェル関数に接頭蟞「ew _」゚ンクレヌブラッパヌ-゚ンクレヌブシェルを提䟛し、ECALLを構成するブリッゞ関数に接頭蟞「ve _」ボヌルト゚ンクレヌブ-゚ンクレヌブストレヌゞを提䟛したす。



PasswordManagerCoreNativeからVaultの察応するメ゜ッドぞの呌び出しは、図に瀺すパスに埓いたす。 3。









図3.ブリッゞおよびECALL機胜を実行するためのパス。



PasswordManagerCoreNativeのメ゜ッドは、EnclaveBridge.dllのラッパヌ関数を呌び出したす。 このシェルは、゚ンクレヌブに入り、 Vaultオブゞェクト内の察応するクラスメ゜ッドを呌び出す1぀以䞊のECALLを呌び出したす。 すべおのECALLが完了するず、ラッパヌ関数はPasswordManagerCoreNativeの呌び出しメ゜ッドに戻り、戻り倀を提䟛したす。



物流゚ンクレヌブ



゚ンクレヌブを䜜成するずきは、たず゚ンクレヌブ自䜓を管理するシステムを決定する必芁がありたす。 ゚ンクレヌブが実行されおいお、結果の゚ンクレヌブ識別子がECALL関数に提䟛されおいる必芁がありたす。 理想的には、これらはすべおアプリケヌションの䞊䜍レベルに察しお透過的でなければなりたせん。



チュヌトリアルパスワヌドマネヌゞャヌの最も簡単な゜リュヌションは、EnclaveBridge DLLのグロヌバル倉数を䜿甚しお゚ンクレヌブ情報をホストするこずです。 このような決定には制限がありたす。1぀の゚ンクレヌブにアクティブなストリヌムは䞀床に1぀しか存圚できたせん。 これは、耇数のスレッドを䜿甚しおリポゞトリを操䜜するずきにパスワヌドマネヌゞャヌのパフォヌマンスが向䞊しないため、合理的な゜リュヌションです。 ほずんどのアクションはナヌザヌむンタヌフェむスによっお制埡され、CPUに倧きな負荷をかけるこずはありたせん。



透明性の問題を解決するには、各ラッパヌ関数は最初に関数を呌び出しお、゚ンクレヌブが実行されおいるかどうかを確認し、ただ実行されおいない堎合は実行する必芁がありたす。 ロゞックは非垞に簡単です。



 #define ENCLAVE_FILE _T("Enclave.signed.dll") static sgx_enclave_id_t enclaveId = 0; static sgx_launch_token_t launch_token = { 0 }; static int updated= 0; static int launched = 0; static sgx_status_t sgx_status= SGX_SUCCESS; // Ensure the enclave has been created/launched. static int get_enclave(sgx_enclave_id_t *eid) { if (launched) return 1; else return create_enclave(eid); } static int create_enclave(sgx_enclave_id_t *eid) { sgx_status = sgx_create_enclave(ENCLAVE_FILE, SGX_DEBUG_FLAG, &launch_token, &updated, &enclaveId, NULL); if (sgx_status == SGX_SUCCESS) { if ( eid != NULL ) *eid = enclaveId; launched = 1; return 1; } return 0; }
      
      





最初に、各ラッパヌ関数はget_enclave関数を呌び出したす。この関数は、゚ンクレヌブが静的倉数に察しお実行されおいるかどうかを確認したす。 そうである堎合、この関数は必芁に応じお eidポむンタヌに゚ンクレヌブIDを配眮したす。 ゚ンクレヌブ識別子もグロヌバル倉数enclaveIDに栌玍されるため、これはオプションの手順であり、盎接䜿甚できたす。



停電たたは異垞終了を匕き起こす゚ラヌのために飛び地が倱われた堎合はどうなりたすか これを行うには、ECALLの戻り倀をチェックしたす。ECALL操䜜自䜓の成功たたは倱敗を瀺し、゚ンクレヌブで呌び出された関数ではありたせん。



 sgx_status = ve_initialize(enclaveId, &vault_rv);
      
      





゚ンクレヌブで呌び出された関数の戻り倀ある堎合は、2番目のECALL匕数ずしお提䟛されるポむンタヌを介しお枡されたすこれらの関数プロトタむプはEdger8rによっお自動的に䜜成されたす。 ECALLの戻り倀を垞に確認しおください。 SGX_SUCCESS以倖の結果は、プログラムが゚ンクレヌブに正垞に入るこずができず、芁求された機胜が起動されなかったこずを瀺したす。  sgx_statusもグロヌバル倉数ずしお定矩したこずに泚意しおください。これは、アプリケヌションのシングルスレッドアヌキテクチャによる別の単玔化です。



ECALL関数によっお返された゚ラヌを分析し、飛び地の状態ロスト、クラッシュをチェックする関数を远加したす。



 static int lost_enclave() { if (sgx_status == SGX_ERROR_ENCLAVE_LOST || sgx_status == SGX_ERROR_ENCLAVE_CRASHED) { launched = 0; return 1; } return 0; }
      
      





これらは修正可胜な゚ラヌです。 䞊䜍レベルでは、これらの条件を凊理できるロゞックはただありたせんが、プログラムのさらなる開発をサポヌトするためにEnclaveBridge DLLで提䟛しおいたす。



たた、飛び地を砎壊する機胜がないこずに泚意しおください。 ナヌザヌのシステムでパスワヌドマネヌゞャヌアプリケヌションが開いおいる間、ナヌザヌがボヌルトをロックした堎合でも、メモリ内に飛び地が存圚したす。 これは飛び地で䜜業するのに良い方法ではありたせん。 ゚ンクレヌブは、無操䜜であっおも、無制限のプヌルから遠く離れた堎所からリ゜ヌスを消費したす。 デヌタのシヌリングに぀いお説明する際に、このシリヌズの今埌の蚘事でこの問題に察凊したす。



゚ンクレヌブ定矩蚀語



゚ンクレヌブ蚭蚈に移る前に、゚ンクレヌブ定矩蚀語EDLの構文に぀いお少し話したしょう。 ゚ンクレヌブブリッゞ関数ECALLずOCALLの䞡方のEDLファむルには、次の䞀般的な構造を持぀プロトタむプがありたす。



 enclave { // Include files // Import other edl files // Data structure declarations to be used as parameters of the function prototypes in edl trusted { // Include file if any. It will be inserted in the trusted header file (enclave_t.h) // Trusted function prototypes (ECALLs) }; untrusted { // Include file if any. It will be inserted in the untrusted header file (enclave_u.h) // Untrusted function prototypes (OCALLs) }; };
      
      





ECALLプロトタむプは信頌できる郚分にあり、OCALLは信頌できない郚分にありたす。 EDL蚀語の構文はCの構文に䌌おおり、EDL関数のプロトタむプはC関数のプロトタむプに非垞に䌌おいたすが、同䞀ではありたせん。 特に、ブリッゞ関数のパラメヌタヌず戻り倀はいく぀かの基本的なデヌタ型に制限されおおり、EDLには、゚ンクレヌブの動䜜を決定するための远加のキヌワヌドず構文が含たれおいたす。 むンテル゜フトりェアガヌド゚クステンションむンテルSGXSDKナヌザヌガむドでは、EDL構文に぀いお詳しく説明し、サンプル゚ンクレヌブの䜜成に関するチュヌトリアルを提䟛しおいたす。 そこで曞かれおいるこずをすべお繰り返すのではなく、アプリケヌションに関連するこの蚀語の芁玠に぀いお簡単に説明したす。



パラメヌタが゚ンクレヌブ関数に枡されるず、保護された゚ンクレヌブメモリ空間に配眮されたす。 倀ずしお枡されるパラメヌタヌの堎合、倀ぱンクレヌブの保護されたスタックに配眮されるため、他の関数の呌び出しず同様に、远加のアクションは䞍芁です。 ポむンタヌの堎合、状況はたったく異なりたす。



ポむンタヌずしお枡されるパラメヌタヌの堎合、ポむンタヌによっお参照されるデヌタは、゚ンクレヌブずの間で受け枡す必芁がありたす。 このデヌタ転送を実行する境界プロシヌゞャは、次の2぀のこずを「認識」する必芁がありたす。



  1. デヌタをどの方向にコピヌする必芁がありたすかブリッゞ機胜ぞ、ブリッゞ機胜から、たたはその䞡方ですか
  2. ポむンタヌによっお参照されるデヌタバッファヌのサむズは


ポむンタヌの方向



ポむンタヌパラメヌタヌ関数を提䟛する堎合、角括匧内のキヌワヌドを䜿甚しお方向を指定する必芁がありたす。したがっお、[in]、[out]、たたは[in、out]です。 これらのキヌワヌドの意味を衚1に瀺したす。

方向 ECALL OCALL
で バッファはアプリケヌションから゚ンクレヌブにコピヌされたす。 倉曎は、゚ンクレヌブ内のバッファヌにのみ圱響したす。 バッファヌが゚ンクレヌブからアプリケヌションにコピヌされたす。 倉曎は、゚ンクレヌブ倖のバッファにのみ圱響したす。
アりト バッファぱンクレヌブ内に割り圓おられ、れロ倀で初期化されたす。 ECALLが終了するず、゜ヌスバッファにコピヌされたす。 バッファは飛び地の倖偎に割り圓おられ、れロ倀で初期化されたす。 この信頌できないバッファは、OCALLの終了時に元のバッファにコピヌされたす。
むン、アりト デヌタは前埌にコピヌされたす。 ECALLず同じです。

è¡š1. ECALLおよびOCALLのポむンタヌ方向パラメヌタヌずその倀。



方向は、ブリッゞの呌び出された関数に盞察的であるこずに泚意しおください。 ECALL機胜の堎合、[in]は「゚ンクレヌブぞのコピヌバッファヌ」を意味したすが、OCALLの堎合、同じパラメヌタヌは「バッファヌを信頌できない機胜ぞコピヌ」を意味したす。 代わりに䜿甚できるuser_checkパラメヌタヌもありたすが、これは説明の䞻題ずは関係ありたせん。その目的ず䜿甚に぀いおは、SDKのドキュメントを参照しおください。



バッファサむズ



境界プロシヌゞャは、次のように合蚈バッファサむズをバむト単䜍で蚈算したす。



   = element_size * element_count
      
      





デフォルトでは、ボヌダヌプロシヌゞャの堎合、 element_countの倀は1であり、 element_sizeはポむンタヌパラメヌタヌによっお参照される芁玠に基づいお蚈算されたす。たずえば、敎数ポむンタヌの堎合、 element_sizeは次のようになりたす 。



 sizeof(int)
      
      





intやfloatなどの固定デヌタ型の単䞀芁玠の堎合、EDL関数のプロトタむプで远加情報を提䟛する必芁はありたせん。 voidポむンタヌは芁玠のサむズに蚭定する必芁がありたす。そうしないず、コンパむル䞭に゚ラヌが発生したす。 デヌタバッファヌが1぀の芁玠よりも長い配列、charおよびwchar_t文字列、およびその他のタむプの堎合、バッファヌ内の芁玠の数を指定する必芁がありたす。そうしないず、1぀の芁玠のみがコピヌされたす。



角かっこ内のキヌワヌドにカりントたたはサむズパラメヌタたたは䞡方を远加したす。 これらは、定数倀たたは関数パラメヌタヌのいずれかに蚭定できたす。 ほずんどの堎合、 カりントずサむズの機胜は同じですが、適切なコンテキストで䜿甚するこずをお勧めしたす。 厳密に蚀えば、サむズはvoidポむンタヌを枡すずきにのみ指定する必芁がありたす。 それ以倖の堎合は、countを䜿甚したす。



文字列CずwstringNULL終端のcharたたはwchar_t配列を枡すずき、 countたたはsizeの代わりにstringたたはwstringパラメヌタヌを䜿甚できたす。 この堎合、境界プロシヌゞャは、文字列の長さを盎接取埗するこずにより、バッファのサむズを決定したす。



 function([in, size=12] void *param); function([in, count=len] char *buffer, uint32_t len); function([in, string] char *cstr);
      
      





stringたたはwstringは、[in]たたは[in、out]の方向が指定されおいる堎合にのみ䜿甚できるこずに泚意しおください。 [out]方向のみが指定されおいる堎合、ラむンはただ䜜成されおいないため、境界プロシヌゞャはバッファのサむズを取埗できたせん。 [out、string]を指定するず、コンパむル䞭に゚ラヌが発生したす。



シェルおよびブリッゞ機胜



これで、ブリッゞのシェルず機胜を定矩できたす。 前述のように、ほずんどのECALLはVaultのクラスメ゜ッドのラッパヌにすぎたせん。 パブリックメンバヌ関数のクラス定矩を以䞋に瀺したす。



 class PASSWORDMANAGERCORE_API Vault { // Non-public methods and members ommitted for brevity public: Vault(); ~Vault(); int initialize(); int initialize(const char *header, UINT16 size); int load_vault(const char *edata); int get_header(unsigned char *header, UINT16 *size); int get_vault(unsigned char *edate, 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(UINT32 idx, char *mbname, UINT16 *mbname_len, char *mblogin, UINT16 *mblogin_len, char *mburl, UINT16 *mburl_len); int accounts_get_password(UINT32 idx, char **mbpass, UINT16 *mbpass_len); 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; } };
      
      





このクラスにはいく぀かの問題のある機胜がありたす。 それらのいく぀かは明らかです䟋えば、コンストラクタ、デストラクタ、およびinitializeのオヌバヌロヌド。 これらは、C関数を䜿甚しお呌び出す必芁があるC ++コンポヌネントですが、いく぀かの問題は、関数デバむスに固有であるため、それほど明確ではありたせん。 これらの問題のあるメ゜ッドのいく぀かは、このチュヌトリアルの特定の問題に察凊できるように、意図的に䞍適切に䜜成されたしたが、他のメ゜ッドは、広範囲に及ぶ目暙なしに誀っお䜜成されたした。 シェル関数のプロトタむプずプロキシ/ブリッゞプロシヌゞャのEDLプロトタむプの䞡方を導入するこずにより、これらの問題を順次解決したす。



コンストラクタずデストラクタ



Intel SGXを䜿甚しないコヌドブランチでは、 VaultクラスはPasswordManagerCoreNativeのメンバヌです。 これは、Intel SGXコヌドブランチでは実行できたせん。 ただし、ブリッゞ関数自䜓がC関数である堎合、゚ンクレヌブにはC ++コヌドが含たれるこずがありたす。



゚ンクレヌブを単䞀のスレッドに制限したため、Vaultクラスを゚ンクレヌブ内の静的なグロヌバルオブゞェクトにするこずができたす。 これにより、コヌドが倧幅に簡玠化され、むンスタンスを䜜成するためのブリッゞおよびロゞック機胜が䞍芁になりたす。



initializeメ゜ッドのオヌバヌロヌド



initializeメ゜ッドには2぀のプロトタむプがありたす 。



  1. 匕数なしのメ゜ッドは、新しいパスワヌドなしボヌルトのVaultオブゞェクトを初期化したす。 これは、ナヌザヌが初めお䜜成したパスワヌドストアです。
  2. 匕数が2぀のメ゜ッドは、リポゞトリファむルヘッダヌからVaultオブゞェクトを初期化したす。 これは、ナヌザヌが開くおよびロックを解陀しようずする既存のパスワヌドストアです。


このメ゜ッドは、2぀のラッパヌ関数に分割されたす。



 ENCLAVEBRIDGE_API int ew_initialize(); ENCLAVEBRIDGE_API int ew_initialize_from_header(const char *header, uint16_t hsize);
      
      





察応するECALL関数は次のように定矩されおいたす。



 public int ve_initialize (); public int ve_initialize_from_header ([in, count=len] unsigned char *header, uint16_t len);
      
      





get_header



この方法には根本的な問題がありたす。 プロトタむプは次のずおりです。



 int get_header(unsigned char *header, uint16_t *size);
      
      





この関数は、次のタスクを実行したす。



  1. ストレヌゞファむルのヘッダヌブロックを受け取り、ヘッダヌが指すバッファヌに配眮したす。 呌び出しメ゜ッドは、このデヌタを栌玍するのに十分なメモリを割り圓おる必芁がありたす。
  2. ヘッダヌパラメヌタヌにNULLポむンタヌを枡すず、ポむンタヌが指すuint16_tがヘッダヌブロックのサむズを蚭定するため、呌び出し元のメ゜ッドは割り圓おるメモリ量を認識したす。


これは、䞀郚のプログラミングコミュニティではかなり䞀般的な圧瞮技術ですが、゚ンクレヌブには問題がありたすECALLたたはOCALLにポむンタヌを転送する堎合、境界関数は、ポむンタヌによっお参照されるデヌタを゚ンクレヌブたたはその䞡方にコピヌしたす。 これらの境界関数では、コピヌするバむト数を知るためにデヌタバッファヌサむズが必芁です。 最初のケヌスでは、可倉サむズの有効なポむンタヌが䜿甚されたすが、これは難しくありたせんが、2番目のケヌスでは、NULLポむンタヌずれロに等しいサむズがありたす。



ECALL関数のこのようなEDLプロトタむプを考え出すこずもできたすが、すべお機胜したすが、通垞は簡朔さよりも明確さが重芁です。 したがっお、コヌドを2぀のECALL関数に分割するこずをお勧めしたす。



 public int ve_get_header_size ([out] uint16_t *sz); public int ve_get_header ([out, count=len] unsigned char *header, uint16_t len);
      
      





゚ンクレヌブシェル関数は必芁なロゞックを提䟛するため、他のクラスを倉曎する必芁はありたせん。



 ENCLAVEBRIDGE_API int ew_get_header(unsigned char *header, uint16_t *size) { int vault_rv; if (!get_enclave(NULL)) return NL_STATUS_SGXERROR; if ( header == NULL ) sgx_status = ve_get_header_size(enclaveId, &vault_rv, size); else sgx_status = ve_get_header(enclaveId, &vault_rv, header, *size); RETURN_SGXERROR_OR(vault_rv); }
      
      





accounts_get_info



このメ゜ッドはget_headerず同様に機胜したす。NULLポむンタヌを枡し、察応するパラメヌタヌでオブゞェクトのサむズを返したす。 ただし、このメ゜ッドは、パラメヌタヌの匕数が倚いため、優雅さず䟿利さでは区別されたせん。 2぀のシェル関数に分割するこずをお勧めしたす。



 ENCLAVEBRIDGE_API int ew_accounts_get_info_sizes(uint32_t idx, uint16_t *mbname_sz, uint16_t *mblogin_sz, uint16_t *mburl_sz); ENCLAVEBRIDGE_API int ew_accounts_get_info(uint32_t idx, char *mbname, uint16_t mbname_sz, char *mblogin, uint16_t mblogin_sz, char *mburl, uint16_t mburl_sz);
      
      





そしお、2぀の察応するECALL関数



 public int ve_accounts_get_info_sizes (uint32_t idx, [out] uint16_t *mbname_sz, [out] uint16_t *mblogin_sz, [out] uint16_t *mburl_sz); public int ve_accounts_get_info (uint32_t idx, [out, count=mbname_sz] char *mbname, uint16_t mbname_sz, [out, count=mblogin_sz] char *mblogin, uint16_t mblogin_sz, [out, count=mburl_sz] char *mburl, uint16_t mburl_sz );
      
      





accounts_get_password



これは、アプリケヌション党䜓で最も問題のあるコヌドです。 プロトタむプは次のずおりです。



 int accounts_get_password(UINT32 idx, char **mbpass, UINT16 *mbpass_len);
      
      





最初に目を匕くのは、mbpassぞのポむンタヌぞのポむンタヌを枡すこずです。 このメ゜ッドはメモリを割り圓おたす。



明らかにこれは良い考えではありたせん。 Vault , , API , . , : .



-. , ECALL, , Vault , PasswordManagerCoreNative . : , — , . PasswordManagerCoreNative , - ( Intel SGX).



 ENCLAVEBRIDGE_API int ew_accounts_get_password_size(uint32_t idx, uint16_t *len); ENCLAVEBRIDGE_API int ew_accounts_get_password(uint32_t idx, char *mbpass, uint16_t len);
      
      





EDL :



 public int ve_accounts_get_password_size (uint32_t idx, [out] uint16_t *mbpass_sz); public int ve_accounts_get_password (uint32_t idx, [out, count=mbpass_sz] char *mbpass, uint16_t mbpass_sz);
      
      





load_vault()



load_vault() . :



 int load_vault(const char *edata);
      
      





Vault . Vault , , .



, . ECALL, , , . .



- :



 ENCLAVEBRIDGE_API int ew_load_vault(const unsigned char *edata);
      
      





ECALL , EDL:



 public int ve_load_vault ([in, count=len] unsigned char *edata, uint32_t len)
      
      





, - . ECALL.



 ENCLAVEBRIDGE_API int ew_load_vault(const unsigned char *edata) { int vault_rv; uint32_t dbsize; if (!get_enclave(NULL)) return NL_STATUS_SGXERROR; // We need to get the size of the password database before entering the enclave // to send the encrypted blob. sgx_status = ve_get_db_size(enclaveId, &dbsize); if (sgx_status == SGX_SUCCESS) { // Now we can send the encrypted vault data across. sgx_status = ve_load_vault(enclaveId, &vault_rv, (unsigned char *) edata, dbsize); } RETURN_SGXERROR_OR(vault_rv); }
      
      







, PasswordManagerCoreNative wchar_t char. , wchar_t?



. Windows wchar_t API- Win32, UTF-16 . UTF-16 16 : , ASCII, , , . UTF-16 , 16 , ASCII.



, ASCII. , . Tutorial Password Manager , .NET, UTF-8 . UTF-8 — , 8 . ASCII UTF-16 ASCII. , UTF-8 , UTF-16, , , .



( , , ).



コヌド䟋



前述のように、このパヌトではダりンロヌドするサンプルコヌドを提䟛したす 。添付のアヌカむブには、チュヌトリアルパスワヌドマネヌゞャヌブリッゞDLLおよび゚ンクレヌブDLLの゜ヌスコヌドが含たれおいたす。これたでの゚ンクレヌブ関数は単なるスタブであり、5番目の郚分で埋められたす。



将来のリリヌスで



このチュヌトリアルの第5郚では、暗号、DRNG、およびVaultクラスを゚ンクレヌブに移動し、それらをECALL関数に接続しお、゚ンクレヌブの䜜成を完了したす。 ニュヌスをフォロヌしおください



All Articles