ã·ãªãŒãºã®ãã®ããŒããšäžç·ã«ããœãŒã¹ã³ãŒãïŒãšã³ã¯ã¬ãŒãä»ãã®å®æããã¢ããªã±ãŒã·ã§ã³ïŒãæäŸãããŸãã ãã®ããŒãžã§ã³ã§ã¯ãIntel SGXã䜿çšããã³ãŒããã©ã³ãã¯ããŒãã³ãŒãã£ã³ã°ãããŠããŸãã
ãšã³ã¯ã¬ãŒãã³ã³ããŒãã³ã
ãšã³ã¯ã¬ãŒãå ã«ã©ã®ã³ã³ããŒãã³ããå®è£ ãããã決å®ããããã«ãã¢ããªã±ãŒã·ã§ã³ã®ã«ãŒãã«ã®ã¯ã©ã¹å³ã«æ»ããŸããããããã«ã€ããŠã¯ã 第3éšã§æåã«èª¬æããŸãããå³ã瀺ããŸãã 1.åãšåæ§ã«ããšã³ã¯ã¬ãŒãå ã®ãªããžã§ã¯ãã¯ç·è²ã®åœ±ä»ãã§ãä¿¡é Œã§ããªãã³ã³ããŒãã³ãã¯éè²ã®åœ±ä»ãã§ãã
å³1.ã€ã³ãã«Software Guard Extensionsã䜿çšãããã¥ãŒããªã¢ã«Password Managerã®ã¯ã©ã¹å³ã
ãã®ã¹ããŒã ã«åŸã£ãŠããšã³ã¯ã¬ãŒãã«è»¢éããå¿ èŠããã4ã€ã®ã¯ã©ã¹ãå®çŸ©ã§ããŸãã
- é庫
- AccountRecord
- æå·
- DRNG
ãã ããäœæ¥ãéå§ããåã«ãã¢ããªã±ãŒã·ã§ã³ããã€ã¹ã«ã€ããŠæ±ºå®ããå¿ èŠããããŸãã ãã®ã¢ããªã±ãŒã·ã§ã³ã¯ã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ã€ã®æ¹æ³ããããŸãã
- ããŒã¿ããŒã¹ããŒããªã³ããã³ãã§çæããããã«ãå€æŽã®ãã³ã«ãã¹ã¿ãŒãã¹ã¯ãŒããå ¥åããããã«ãŠãŒã¶ãŒã«èŠæ±ããã
- ãŠãŒã¶ãŒã®ã¡ã€ã³ãã¹ã¯ãŒãããã£ãã·ã¥ããŠããŠãŒã¶ãŒã®ä»å ¥ãªãã«ãªã³ããã³ãã§ããŒã¿ããŒã¹ããŒãçæããŸãã
- ã¡ã¢ãªå ã®ããŒã¿ããŒã¹ããŒãæå·åããšã³ã³ãŒãããŸãã¯é衚瀺ã«ããŸãã
- ããŒãæå·åããã«ä¿åããŸãã
ãããã®ãœãªã¥ãŒã·ã§ã³ã¯ã©ããæºè¶³ã®ãããã®ã§ã¯ãããŸããã ãã䟿å©ãªãœãªã¥ãŒã·ã§ã³ã®æ¬ åŠã¯ã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 |
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 |
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ã€ã®ãªãã·ã§ã³ããããŸãã
, , , (). |
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 |
DRNG , Crypto ? , . DRNG , DRNG Crypto ( Crypto DRNG ). , Crypto , , API .
sgx_read_rand?
Intel SGX SDK sgx_read_rand , . :
- Intel SGX SDK, « C , , rand , srand ., ». sgx_read_rand RDRAND, , , srand rand , C. , C, . , - , , , , CPUID, , .
- Intel SGX SDK RDSEED. , . RDRAND sgx_read_rand , , .
- , sgx_read_rand , .
. , , , .
, .
Tutorial Password Manager, -. , ; , Intel SGX.
å°æ¥ã®ãªãªãŒã¹ã§
, , Intel SGX. ãã¥ãŒã¹ããã©ããŒããŠãã ããïŒ
Intel Software Guard Extensions Tutorial Series .