Micro$oft Crypto Nonsense
authorVolker Birk <vb@pep-project.org>
Thu, 23 Jun 2016 21:08:02 +0200
changeset 1236d311985ee41
parent 121 6ee2155ec27a
child 124 ce9401d49537
Micro$oft Crypto Nonsense
GateKeeper.cpp
GateKeeper.h
pEpCOMServerAdapter.vcxproj
stdafx.h
updatekey.bin
     1.1 --- a/GateKeeper.cpp	Wed Jun 22 13:28:02 2016 +0200
     1.2 +++ b/GateKeeper.cpp	Thu Jun 23 21:08:02 2016 +0200
     1.3 @@ -2,9 +2,112 @@
     1.4  
     1.5  #include "GateKeeper.h"
     1.6  #include "pEpCOMServerAdapter.h"
     1.7 +#include "utf8_helper.h"
     1.8  
     1.9  using namespace std;
    1.10  
    1.11 +// https://gist.github.com/mcdurdin/5626617
    1.12 +
    1.13 +struct PUBLIC_KEY_VALUES {
    1.14 +    BLOBHEADER blobheader;
    1.15 +    RSAPUBKEY rsapubkey;
    1.16 +    BYTE modulus[4096];
    1.17 +};
    1.18 +
    1.19 +static void ReverseMemCopy(
    1.20 +    _Out_ BYTE       *pbDest,
    1.21 +    _In_  BYTE const *pbSource,
    1.22 +    _In_  DWORD       cb
    1.23 +    )
    1.24 +{
    1.25 +    for (DWORD i = 0; i < cb; i++) {
    1.26 +        pbDest[cb - 1 - i] = pbSource[i];
    1.27 +    }
    1.28 +}
    1.29 +
    1.30 +static NTSTATUS ImportRsaPublicKey(
    1.31 +    _In_ BCRYPT_ALG_HANDLE  hAlg,    // CNG provider
    1.32 +    _In_ PUBLIC_KEY_VALUES *pKey,    // Pointer to the RSAPUBKEY blob.
    1.33 +    _In_ BCRYPT_KEY_HANDLE *phKey    // Receives a handle the imported public key.
    1.34 +    )
    1.35 +{
    1.36 +    NTSTATUS hr = 0;
    1.37 +
    1.38 +    BYTE *pbPublicKey = NULL;
    1.39 +    DWORD cbKey = 0;
    1.40 +
    1.41 +    // Layout of the RSA public key blob:
    1.42 +
    1.43 +    //  +----------------------------------------------------------------+
    1.44 +    //  |     BCRYPT_RSAKEY_BLOB    | BE( dwExp ) |   BE( Modulus )      |
    1.45 +    //  +----------------------------------------------------------------+
    1.46 +    //
    1.47 +    //  sizeof(BCRYPT_RSAKEY_BLOB)       cbExp           cbModulus 
    1.48 +    //  <--------------------------><------------><---------------------->
    1.49 +    //
    1.50 +    //   BE = Big Endian Format                                                     
    1.51 +
    1.52 +    DWORD cbModulus = (pKey->rsapubkey.bitlen + 7) / 8;
    1.53 +    DWORD dwExp = pKey->rsapubkey.pubexp;
    1.54 +    DWORD cbExp = (dwExp & 0xFF000000) ? 4 :
    1.55 +        (dwExp & 0x00FF0000) ? 3 :
    1.56 +        (dwExp & 0x0000FF00) ? 2 : 1;
    1.57 +
    1.58 +    BCRYPT_RSAKEY_BLOB *pRsaBlob;
    1.59 +    PBYTE pbCurrent;
    1.60 +
    1.61 +    if (!SUCCEEDED(hr = DWordAdd(cbModulus, sizeof(BCRYPT_RSAKEY_BLOB), &cbKey))) {
    1.62 +        goto cleanup;
    1.63 +    }
    1.64 +
    1.65 +    cbKey += cbExp;
    1.66 +
    1.67 +    pbPublicKey = (PBYTE) CoTaskMemAlloc(cbKey);
    1.68 +    if (pbPublicKey == NULL) {
    1.69 +        hr = E_OUTOFMEMORY;
    1.70 +        goto cleanup;
    1.71 +    }
    1.72 +
    1.73 +    ZeroMemory(pbPublicKey, cbKey);
    1.74 +    pRsaBlob = (BCRYPT_RSAKEY_BLOB *) (pbPublicKey);
    1.75 +
    1.76 +    //
    1.77 +    // Make the Public Key Blob Header
    1.78 +    //
    1.79 +
    1.80 +    pRsaBlob->Magic = BCRYPT_RSAPUBLIC_MAGIC;
    1.81 +    pRsaBlob->BitLength = pKey->rsapubkey.bitlen;
    1.82 +    pRsaBlob->cbPublicExp = cbExp;
    1.83 +    pRsaBlob->cbModulus = cbModulus;
    1.84 +    pRsaBlob->cbPrime1 = 0;
    1.85 +    pRsaBlob->cbPrime2 = 0;
    1.86 +
    1.87 +    pbCurrent = (PBYTE) (pRsaBlob + 1);
    1.88 +
    1.89 +    //
    1.90 +    // Copy pubExp Big Endian 
    1.91 +    //
    1.92 +
    1.93 +    ReverseMemCopy(pbCurrent, (PBYTE) &dwExp, cbExp);
    1.94 +    pbCurrent += cbExp;
    1.95 +
    1.96 +    //
    1.97 +    // Copy Modulus Big Endian 
    1.98 +    //
    1.99 +
   1.100 +    ReverseMemCopy(pbCurrent, pKey->modulus, cbModulus);
   1.101 +
   1.102 +    //
   1.103 +    // Import the public key
   1.104 +    //
   1.105 +
   1.106 +    hr = BCryptImportKeyPair(hAlg, NULL, BCRYPT_RSAPUBLIC_BLOB, phKey, (PUCHAR) pbPublicKey, cbKey, 0);
   1.107 +
   1.108 +cleanup:
   1.109 +    CoTaskMemFree(pbPublicKey);
   1.110 +    return hr;
   1.111 +}
   1.112 +
   1.113  namespace pEp {
   1.114  
   1.115      const LPCTSTR GateKeeper::plugin_reg_path = _T("Software\\Microsoft\\Office\\Outlook\\Addins\\pEp");
   1.116 @@ -82,7 +185,7 @@
   1.117          while (!_self->m_bComInitialized)
   1.118              Sleep(1);
   1.119  
   1.120 -        MessageBox(NULL, _T("test"), _T("keep_plugin"), MB_ICONINFORMATION | MB_TOPMOST);
   1.121 +        //MessageBox(NULL, _T("test"), _T("keep_plugin"), MB_ICONINFORMATION | MB_TOPMOST);
   1.122  
   1.123          DWORD value;
   1.124          DWORD size;
   1.125 @@ -126,10 +229,10 @@
   1.126          static random_device rd;
   1.127          static mt19937 gen(rd());
   1.128  
   1.129 -        uniform_int_distribution<time_t> dist(0, UINT64_MAX);
   1.130 +        uniform_int_distribution<int64_t> dist(0, UINT32_MAX);
   1.131  
   1.132 -        key.qw_key[0] = dist(gen);
   1.133 -        key.qw_key[1] = dist(gen);
   1.134 +        for (int i = 0; i < 8; i++)
   1.135 +            key.dw_key[i] = (uint32_t) dist(gen);
   1.136  
   1.137          BCRYPT_KEY_HANDLE hKey;
   1.138          NTSTATUS status = BCryptGenerateSymmetricKey(hAES, &hKey, NULL, 0, (PUCHAR) &key, (ULONG) sizeof(aeskey_t), 0);
   1.139 @@ -147,23 +250,39 @@
   1.140          BCRYPT_KEY_HANDLE hUpdateKey;
   1.141          string _update_key = update_key();
   1.142  
   1.143 -        NTSTATUS status = BCryptImportKeyPair(hRSA, NULL, BCRYPT_RSAPUBLIC_BLOB, &hUpdateKey,
   1.144 -                (PUCHAR) _update_key.data(), _update_key.size(), 0);
   1.145 -        if (status)
   1.146 -            throw runtime_error("BCryptImportKeyPair: update_key");
   1.147 +        PCERT_PUBLIC_KEY_INFO uk;
   1.148 +        DWORD uk_size;
   1.149 +        BOOL bResult = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
   1.150 +                (const BYTE *) _update_key.data(), _update_key.size(), CRYPT_DECODE_ALLOC_FLAG, NULL, &uk, &uk_size);
   1.151 +        if (!bResult)
   1.152 +            throw runtime_error("CryptDecodeObjectEx: X509_PUBLIC_KEY_INFO");
   1.153 +
   1.154 +        PUBLIC_KEY_VALUES *_uk;
   1.155 +        DWORD _uk_size;
   1.156 +        bResult = CryptDecodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
   1.157 +            uk->PublicKey.pbData, uk->PublicKey.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &_uk, &_uk_size);
   1.158 +        LocalFree(uk);
   1.159 +        if (!bResult)
   1.160 +            throw runtime_error("CryptDecodeObjectEx: X509_PUBLIC_KEY_INFO");
   1.161 +
   1.162 +        HRESULT hResult = ImportRsaPublicKey(hRSA, _uk, &hUpdateKey);
   1.163 +        LocalFree(_uk);
   1.164 +        if (hResult)
   1.165 +            throw runtime_error("ImportRsaPublicKey");
   1.166  
   1.167          aeskey_t _delivery_key;
   1.168          ULONG copied;
   1.169 -        status = BCryptExportKey(hDeliveryKey, NULL, BCRYPT_KEY_DATA_BLOB, (PUCHAR) &_delivery_key, sizeof(aeskey_t), &copied, 0);
   1.170 +        NTSTATUS status = BCryptExportKey(hDeliveryKey, NULL, BCRYPT_KEY_DATA_BLOB, (PUCHAR) &_delivery_key, sizeof(aeskey_t),
   1.171 +                &copied, 0);
   1.172          if (status)
   1.173              throw runtime_error("BCryptExportKey: delivery_key");
   1.174  
   1.175          static random_device rd;
   1.176          static mt19937 gen(rd());
   1.177 -        uniform_int_distribution<time_t> dist(0, UINT64_MAX);
   1.178 -        uint64_t r[32];
   1.179 -        for (int i = 0; i < 32; i++)
   1.180 -            r[i] = dist(gen);
   1.181 +        uniform_int_distribution<int64_t> dist(0, UINT32_MAX);
   1.182 +        uint32_t r[64];
   1.183 +        for (int i = 0; i < 64; i++)
   1.184 +            r[i] = (uint32_t) dist(gen);
   1.185  
   1.186          BCRYPT_OAEP_PADDING_INFO pi;
   1.187          memset(&pi, 0, sizeof(BCRYPT_OAEP_PADDING_INFO));
   1.188 @@ -224,6 +343,8 @@
   1.189  
   1.190      void GateKeeper::update_product(product p, DWORD context)
   1.191      {
   1.192 +        string delivery = wrapped_delivery_key(delivery_key());
   1.193 +
   1.194          HINTERNET hUrl = InternetOpenUrl(internet, p.second.c_str(), NULL, 0,
   1.195                  INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_UI | INTERNET_FLAG_SECURE, context);
   1.196          if (hUrl == NULL)
   1.197 @@ -252,8 +373,8 @@
   1.198              goto closing;
   1.199  
   1.200          internet = InternetOpen(_T("pEp"), INTERNET_OPEN_TYPE_PROXY, NULL, NULL, 0);
   1.201 -        if (!internet)
   1.202 -            goto closing;
   1.203 +        //if (!internet)
   1.204 +        //    goto closing;
   1.205  
   1.206          product_list& products = registered_products();
   1.207          DWORD context = 0;
     2.1 --- a/GateKeeper.h	Wed Jun 22 13:28:02 2016 +0200
     2.2 +++ b/GateKeeper.h	Thu Jun 23 21:08:02 2016 +0200
     2.3 @@ -15,10 +15,10 @@
     2.4          typedef pair<tstring, tstring> product;
     2.5          typedef vector< product > product_list;
     2.6          union aeskey_t {
     2.7 -            uint8_t c_key[16];
     2.8 -            uint16_t w_key[8];
     2.9 -            uint32_t dw_key[4];
    2.10 -            uint64_t qw_key[2];
    2.11 +            uint8_t c_key[132];
    2.12 +            uint16_t w_key[16];
    2.13 +            uint32_t dw_key[8];
    2.14 +            uint64_t qw_key[4];
    2.15          };
    2.16  
    2.17          GateKeeper(CpEpCOMServerAdapterModule * self);
     3.1 --- a/pEpCOMServerAdapter.vcxproj	Wed Jun 22 13:28:02 2016 +0200
     3.2 +++ b/pEpCOMServerAdapter.vcxproj	Thu Jun 23 21:08:02 2016 +0200
     3.3 @@ -85,7 +85,7 @@
     3.4        <SubSystem>Windows</SubSystem>
     3.5        <GenerateDebugInformation>true</GenerateDebugInformation>
     3.6        <RegisterOutput>false</RegisterOutput>
     3.7 -      <AdditionalDependencies>comsuppwd.lib;%(AdditionalDependencies);Wininet.lib;bcrypt.lib</AdditionalDependencies>
     3.8 +      <AdditionalDependencies>comsuppwd.lib;%(AdditionalDependencies);Wininet.lib;bcrypt.lib;Crypt32.lib</AdditionalDependencies>
     3.9        <PerUserRedirection>true</PerUserRedirection>
    3.10      </Link>
    3.11    </ItemDefinitionGroup>
    3.12 @@ -120,7 +120,7 @@
    3.13        <EnableCOMDATFolding>true</EnableCOMDATFolding>
    3.14        <OptimizeReferences>true</OptimizeReferences>
    3.15        <RegisterOutput>true</RegisterOutput>
    3.16 -      <AdditionalDependencies>comsuppw.lib;%(AdditionalDependencies);Wininet.lib;bcrypt.lib</AdditionalDependencies>
    3.17 +      <AdditionalDependencies>comsuppw.lib;%(AdditionalDependencies);Wininet.lib;bcrypt.lib;Crypt32.lib</AdditionalDependencies>
    3.18      </Link>
    3.19    </ItemDefinitionGroup>
    3.20    <ItemGroup>
     4.1 --- a/stdafx.h	Wed Jun 22 13:28:02 2016 +0200
     4.2 +++ b/stdafx.h	Thu Jun 23 21:08:02 2016 +0200
     4.3 @@ -28,6 +28,7 @@
     4.4  #include <comutil.h>
     4.5  
     4.6  #include <Wininet.h>
     4.7 +#include <intsafe.h>
     4.8  #include <bcrypt.h>
     4.9  
    4.10  #include <vector>
     5.1 Binary file updatekey.bin has changed