3 #include "GateKeeper.h"
4 #include "pEpCOMServerAdapter.h"
10 const LPCTSTR GateKeeper::plugin_reg_path = _T("Software\\Microsoft\\Office\\Outlook\\Addins\\pEp");
11 const LPCTSTR GateKeeper::plugin_reg_value_name = _T("LoadBehavior");
12 const LPCTSTR GateKeeper::updater_reg_path = _T("Software\\pEp\\Updater";)
14 const time_t GateKeeper::cycle = 7200; // 7200 sec is 2 h
15 const DWORD GateKeeper::waiting = 10000; // 10000 ms is 10 sec
17 GateKeeper::GateKeeper(CpEpCOMServerAdapterModule * self)
18 : _self(self), now(time(NULL)), next(now + time_diff()), hkUpdater(NULL), internet(NULL), hAES(NULL), hRSA(NULL)
20 LONG lResult = RegOpenCurrentUser(KEY_READ, &cu);
21 assert(lResult == ERROR_SUCCESS);
22 if (lResult == ERROR_SUCCESS)
28 LONG lResult = RegOpenKeyEx(cu, updater_reg_path, 0, KEY_READ, &hkUpdater);
29 assert(lResult == ERROR_SUCCESS);
30 if (lResult != ERROR_SUCCESS)
35 GateKeeper::~GateKeeper()
39 RegCloseKey(hkUpdater);
44 time_t GateKeeper::time_diff()
47 static random_device rd;
48 static mt19937 gen(rd());
50 uniform_int_distribution<time_t> dist(0, cycle);
60 void GateKeeper::keep()
72 next = now + GateKeeper::cycle;
80 void GateKeeper::keep_plugin()
82 while (!_self->m_bComInitialized)
85 MessageBox(NULL, _T("test"), _T("keep_plugin"), MB_ICONINFORMATION | MB_TOPMOST);
90 LONG lResult = RegGetValue(cu, plugin_reg_path, plugin_reg_value_name, RRF_RT_REG_DWORD, NULL, &value, &size);
91 if (lResult != ERROR_SUCCESS)
95 lResult = RegSetValue(cu, plugin_reg_path, RRF_RT_REG_DWORD, plugin_reg_value_name, 3);
96 assert(lResult == ERROR_SUCCESS);
100 string GateKeeper::update_key()
104 if (key.length() == 0) {
105 HRSRC res = FindResource(_self->hModule(), MAKEINTRESOURCE(IRD_UPDATEKEY), RT_RCDATA);
108 throw runtime_error("FindResource: IRD_UPDATEKEY");
110 HGLOBAL hRes = LoadResource(_self->hModule(), res);
113 throw runtime_error("LoadResource: IRD_UPDATEKEY");
115 key = string((char *)LockResource(hRes), SizeofResource(_self->hModule(), res));
116 UnlockResource(hRes);
122 BCRYPT_KEY_HANDLE GateKeeper::delivery_key()
126 static random_device rd;
127 static mt19937 gen(rd());
129 uniform_int_distribution<time_t> dist(0, UINT64_MAX);
131 key.qw_key[0] = dist(gen);
132 key.qw_key[1] = dist(gen);
134 BCRYPT_KEY_HANDLE hKey;
135 NTSTATUS status = BCryptGenerateSymmetricKey(hAES, &hKey, NULL, 0, (PUCHAR) &key, (ULONG) sizeof(aeskey_t), 0);
138 throw runtime_error("BCryptGenerateSymmetricKey");
143 string GateKeeper::wrapped_delivery_key(BCRYPT_KEY_HANDLE hKey)
147 BCRYPT_KEY_HANDLE hUpdateKey;
148 string _update_key = update_key();
150 NTSTATUS status = BCryptImportKeyPair(hRSA, NULL, BCRYPT_RSAPUBLIC_BLOB, &hUpdateKey,
151 (PUCHAR) _update_key.data(), _update_key.size(), 0);
153 throw runtime_error("BCryptImportKeyPair: update_key");
155 static random_device rd;
156 static mt19937 gen(rd());
157 uniform_int_distribution<time_t> dist(0, UINT64_MAX);
159 for (int i = 0; i < 32; i++)
162 BCRYPT_OAEP_PADDING_INFO pi;
163 memset(&pi, 0, sizeof(BCRYPT_OAEP_PADDING_INFO));
164 pi.pszAlgId = BCRYPT_SHA256_ALGORITHM;
165 pi.pbLabel = (PUCHAR) r;
166 pi.cbLabel = sizeof(r);
169 PUCHAR _result = NULL;
170 status = BCryptEncrypt(hUpdateKey, (PUCHAR) _update_key.data(), _update_key.size(), &pi, NULL, 0, NULL, 0, &result_size, BCRYPT_PAD_OAEP);
172 BCryptDestroyKey(hUpdateKey);
173 throw runtime_error("BCryptEncrypt: calculating result size");
176 _result = new UCHAR[result_size];
178 status = BCryptEncrypt(hUpdateKey, (PUCHAR) _update_key.data(), _update_key.size(), &pi, NULL, 0, _result, result_size, &copied, BCRYPT_PAD_OAEP);
180 BCryptDestroyKey(hUpdateKey);
182 throw runtime_error("BCryptEncrypt: encrypting using update_key");
186 s << hex << setw(2) << setfill('0');
187 for (ULONG i = 0; i < copied; i++)
188 s << (int) _result[i];
192 BCryptDestroyKey(hUpdateKey);
196 GateKeeper::product_list& GateKeeper::registered_products()
198 static product_list products;
200 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
201 static TCHAR value_name[16384];
202 DWORD value_name_size;
203 static TCHAR value[L_MAX_URL_LENGTH + 1];
208 LONG lResult = ERROR_SUCCESS;
209 for (DWORD i = 0; lResult == ERROR_SUCCESS; i++) {
210 value_size = L_MAX_URL_LENGTH + 1;
211 lResult = RegEnumValue(hkUpdater, 0, value_name, &value_name_size, NULL, NULL, (LPBYTE) value, &value_size);
212 if (lResult == ERROR_SUCCESS)
213 products.push_back({ value_name, value });
219 void GateKeeper::update_product(product p, DWORD context)
221 HINTERNET hUrl = InternetOpenUrl(internet, p.second.c_str(), NULL, 0,
222 INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_UI | INTERNET_FLAG_SECURE, context);
227 PCTSTR rgpszAcceptTypes[] = { _T("text/plain"), NULL };
228 HINTERNET hRequest = HttpOpenRequest(hUrl, NULL, _T("challenge"), NULL, NULL, rgpszAcceptTypes, INTERNET_FLAG_NO_UI | INTERNET_FLAG_SECURE, context);
231 InternetCloseHandle(hUrl);
234 void GateKeeper::keep_updated()
236 return; // disabled for now
238 NTSTATUS status = BCryptOpenAlgorithmProvider(&hAES, BCRYPT_AES_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
243 status = BCryptOpenAlgorithmProvider(&hRSA, BCRYPT_RSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
248 internet = InternetOpen(_T("pEp"), INTERNET_OPEN_TYPE_PROXY, NULL, NULL, 0);
252 product_list& products = registered_products();
254 for (auto i = products.begin(); i != products.end(); i++) {
255 update_product(*i, context++);
260 InternetCloseHandle(internet);
262 BCryptCloseAlgorithmProvider(hAES, 0);
264 BCryptCloseAlgorithmProvider(hRSA, 0);