⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protectdata.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (rc && !CryptDeriveKey(hProv,CRYPT32_PROTECTDATA_KEY_CALG,
                              hSaltHash,CRYPT_EXPORTABLE,phKey))
    {
        ERR("CryptDeriveKey\n");
        rc = FALSE;
    }

    /* clean up */
    CryptDestroyHash(hSaltHash);
    CryptMemFree(szUsername);

    return rc;
}

/* debugging tool to print the structures of a ProtectData call */
static void
report(const DATA_BLOB* pDataIn, const DATA_BLOB* pOptionalEntropy,
       CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags)
{
    TRACE("pPromptStruct: %p\n", pPromptStruct);
    if (pPromptStruct)
    {
        TRACE("  cbSize: 0x%x\n",(unsigned int)pPromptStruct->cbSize);
        TRACE("  dwPromptFlags: 0x%x\n",(unsigned int)pPromptStruct->dwPromptFlags);
        TRACE("  hwndApp: %p\n", pPromptStruct->hwndApp);
        TRACE("  szPrompt: %p %s\n",
              pPromptStruct->szPrompt,
              pPromptStruct->szPrompt ? debugstr_w(pPromptStruct->szPrompt)
              : "");
    }
    TRACE("dwFlags: 0x%04x\n",(unsigned int)dwFlags);
    TRACE_DATA_BLOB(pDataIn);
    if (pOptionalEntropy)
    {
        TRACE_DATA_BLOB(pOptionalEntropy);
        TRACE("  %s\n",debugstr_an((LPCSTR)pOptionalEntropy->pbData,pOptionalEntropy->cbData));
    }

}


/***************************************************************************
 * CryptProtectData     [CRYPT32.@]
 *
 * Generate Cipher data from given Plain and Entropy data.
 *
 * PARAMS
 *  pDataIn          [I] Plain data to be enciphered
 *  szDataDescr      [I] Optional Unicode string describing the Plain data
 *  pOptionalEntropy [I] Optional entropy data to adjust cipher, can be NULL
 *  pvReserved       [I] Reserved, must be NULL
 *  pPromptStruct    [I] Structure describing if/how to prompt during ciphering
 *  dwFlags          [I] Flags describing options to the ciphering
 *  pDataOut         [O] Resulting Cipher data, for calls to CryptUnprotectData
 *
 * RETURNS
 *  TRUE  If a Cipher was generated.
 *  FALSE If something failed and no Cipher is available.
 *
 * FIXME
 *  The true Windows encryption and keying mechanisms are unknown.
 *
 *  dwFlags and pPromptStruct are currently ignored.
 *
 * NOTES
 *  Memory allocated in pDataOut must be freed with LocalFree.
 *
 */
BOOL WINAPI CryptProtectData(DATA_BLOB* pDataIn,
                             LPCWSTR szDataDescr,
                             DATA_BLOB* pOptionalEntropy,
                             PVOID pvReserved,
                             CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
                             DWORD dwFlags,
                             DATA_BLOB* pDataOut)
{
    static const WCHAR empty_str[1];
    BOOL rc = FALSE;
    HCRYPTPROV hProv;
    struct protect_data_t protect_data;
    HCRYPTHASH hHash;
    HCRYPTKEY hKey;
    DWORD dwLength;

    TRACE("called\n");

    SetLastError(ERROR_SUCCESS);

    if (!pDataIn || !pDataOut)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        goto finished;
    }

    /* debug: show our arguments */
    report(pDataIn,pOptionalEntropy,pPromptStruct,dwFlags);
    TRACE("\tszDataDescr: %p %s\n", szDataDescr,
          szDataDescr ? debugstr_w(szDataDescr) : "");

    /* Windows appears to create an empty szDataDescr instead of maintaining
     * a NULL */
    if (!szDataDescr)
        szDataDescr = empty_str;

    /* get crypt context */
    if (!CryptAcquireContextW(&hProv,NULL,NULL,CRYPT32_PROTECTDATA_PROV,CRYPT_VERIFYCONTEXT))
    {
        ERR("CryptAcquireContextW failed\n");
        goto finished;
    }

    /* populate our structure */
    if (!fill_protect_data(&protect_data,szDataDescr,hProv))
    {
        ERR("fill_protect_data\n");
        goto free_context;
    }

    /* load key */
    if (!load_encryption_key(hProv,&protect_data.salt,pOptionalEntropy,&hKey))
    {
        goto free_protect_data;
    }

    /* create a hash for the encryption validation */
    if (!CryptCreateHash(hProv,CRYPT32_PROTECTDATA_HASH_CALG,0,0,&hHash))
    {
        ERR("CryptCreateHash\n");
        goto free_key;
    }

    /* calculate storage required */
    dwLength=pDataIn->cbData;
    if (CryptEncrypt(hKey, 0, TRUE, 0, pDataIn->pbData, &dwLength, 0) ||
        GetLastError()!=ERROR_MORE_DATA)
    {
        ERR("CryptEncrypt\n");
        goto free_hash;
    }
    TRACE("required encrypted storage: %u\n",(unsigned int)dwLength);

    /* copy plain text into cipher area for CryptEncrypt call */
    protect_data.cipher.cbData=dwLength;
    if (!(protect_data.cipher.pbData=CryptMemAlloc(
                                                protect_data.cipher.cbData)))
    {
        ERR("CryptMemAlloc\n");
        goto free_hash;
    }
    memcpy(protect_data.cipher.pbData,pDataIn->pbData,pDataIn->cbData);

    /* encrypt! */
    dwLength=pDataIn->cbData;
    if (!CryptEncrypt(hKey, hHash, TRUE, 0, protect_data.cipher.pbData,
                      &dwLength, protect_data.cipher.cbData))
    {
        ERR("CryptEncrypt %u\n",(unsigned int)GetLastError());
        goto free_hash;
    }
    protect_data.cipher.cbData=dwLength;

    /* debug: show the cipher */
    TRACE_DATA_BLOB(&protect_data.cipher);

    /* attach our fingerprint */
    if (!convert_hash_to_blob(hHash, &protect_data.fingerprint))
    {
        ERR("convert_hash_to_blob\n");
        goto free_hash;
    }

    /* serialize into an opaque blob */
    if (!serialize(&protect_data, pDataOut))
    {
        ERR("serialize\n");
        goto free_hash;
    }

    /* success! */
    rc=TRUE;

free_hash:
    CryptDestroyHash(hHash);
free_key:
    CryptDestroyKey(hKey);
free_protect_data:
    free_protect_data(&protect_data);
free_context:
    CryptReleaseContext(hProv,0);
finished:
    /* If some error occurred, and no error code was set, force one. */
    if (!rc && GetLastError()==ERROR_SUCCESS)
    {
        SetLastError(ERROR_INVALID_DATA);
    }

    if (rc)
    {
        SetLastError(ERROR_SUCCESS);

        TRACE_DATA_BLOB(pDataOut);
    }

    TRACE("returning %s\n", rc ? "ok" : "FAIL");

    return rc;
}


/***************************************************************************
 * CryptUnprotectData   [CRYPT32.@]
 *
 * Generate Plain data and Description from given Cipher and Entropy data.
 *
 * PARAMS
 *  pDataIn          [I] Cipher data to be decoded
 *  ppszDataDescr    [O] Optional Unicode string describing the Plain data
 *  pOptionalEntropy [I] Optional entropy data to adjust cipher, can be NULL
 *  pvReserved       [I] Reserved, must be NULL
 *  pPromptStruct    [I] Structure describing if/how to prompt during decoding
 *  dwFlags          [I] Flags describing options to the decoding
 *  pDataOut         [O] Resulting Plain data, from calls to CryptProtectData
 *
 * RETURNS
 *  TRUE  If a Plain was generated.
 *  FALSE If something failed and no Plain is available.
 *
 * FIXME
 *  The true Windows encryption and keying mechanisms are unknown.
 *
 *  dwFlags and pPromptStruct are currently ignored.
 *
 * NOTES
 *  Memory allocated in pDataOut and non-NULL ppszDataDescr must be freed
 *  with LocalFree.
 *
 */
BOOL WINAPI CryptUnprotectData(DATA_BLOB* pDataIn,
                               LPWSTR * ppszDataDescr,
                               DATA_BLOB* pOptionalEntropy,
                               PVOID pvReserved,
                               CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
                               DWORD dwFlags,
                               DATA_BLOB* pDataOut)
{
    BOOL rc = FALSE;

    HCRYPTPROV hProv;
    struct protect_data_t protect_data;
    HCRYPTHASH hHash;
    HCRYPTKEY hKey;
    DWORD dwLength;

    const char * announce_bad_opaque_data = "CryptUnprotectData received a DATA_BLOB that seems to have NOT been generated by Wine.  Please enable tracing ('export WINEDEBUG=crypt') to see details.";

    TRACE("called\n");

    SetLastError(ERROR_SUCCESS);

    if (!pDataIn || !pDataOut)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        goto finished;
    }

    /* debug: show our arguments */
    report(pDataIn,pOptionalEntropy,pPromptStruct,dwFlags);
    TRACE("\tppszDataDescr: %p\n", ppszDataDescr);

    /* take apart the opaque blob */
    if (!unserialize(pDataIn, &protect_data))
    {
        SetLastError(ERROR_INVALID_DATA);
        FIXME("%s\n",announce_bad_opaque_data);
        goto finished;
    }

    /* perform basic validation on the resulting structure */
    if (!valid_protect_data(&protect_data))
    {
        SetLastError(ERROR_INVALID_DATA);
        FIXME("%s\n",announce_bad_opaque_data);
        goto free_protect_data;
    }

    /* get a crypt context */
    if (!CryptAcquireContextW(&hProv,NULL,NULL,CRYPT32_PROTECTDATA_PROV,CRYPT_VERIFYCONTEXT))
    {
        ERR("CryptAcquireContextW failed\n");
        goto free_protect_data;
    }

    /* load key */
    if (!load_encryption_key(hProv,&protect_data.salt,pOptionalEntropy,&hKey))
    {
        goto free_context;
    }

    /* create a hash for the decryption validation */
    if (!CryptCreateHash(hProv,CRYPT32_PROTECTDATA_HASH_CALG,0,0,&hHash))
    {
        ERR("CryptCreateHash\n");
        goto free_key;
    }

    /* prepare for plaintext */
    pDataOut->cbData=protect_data.cipher.cbData;
    if (!(pDataOut->pbData=LocalAlloc( LPTR, pDataOut->cbData)))
    {
        ERR("CryptMemAlloc\n");
        goto free_hash;
    }
    memcpy(pDataOut->pbData,protect_data.cipher.pbData,protect_data.cipher.cbData);

    /* decrypt! */
    if (!CryptDecrypt(hKey, hHash, TRUE, 0, pDataOut->pbData,
                      &pDataOut->cbData) ||
        /* check the hash fingerprint */
        pDataOut->cbData > protect_data.cipher.cbData ||
        !hash_matches_blob(hHash, &protect_data.fingerprint))
    {
        SetLastError(ERROR_INVALID_DATA);

        LocalFree( pDataOut->pbData );
        pDataOut->pbData = NULL;
        pDataOut->cbData = 0;

        goto free_hash;
    }

    /* Copy out the description */
    dwLength = (lstrlenW(protect_data.szDataDescr)+1) * sizeof(WCHAR);
    if (ppszDataDescr)
    {
        if (!(*ppszDataDescr = LocalAlloc(LPTR,dwLength)))
        {
            ERR("LocalAlloc (ppszDataDescr)\n");
            goto free_hash;
        }
        else {
            memcpy(*ppszDataDescr,protect_data.szDataDescr,dwLength);
        }
    }

    /* success! */
    rc = TRUE;

free_hash:
    CryptDestroyHash(hHash);
free_key:
    CryptDestroyKey(hKey);
free_context:
    CryptReleaseContext(hProv,0);
free_protect_data:
    free_protect_data(&protect_data);
finished:
    /* If some error occurred, and no error code was set, force one. */
    if (!rc && GetLastError()==ERROR_SUCCESS)
    {
        SetLastError(ERROR_INVALID_DATA);
    }

    if (rc) {
        SetLastError(ERROR_SUCCESS);

        if (ppszDataDescr)
        {
            TRACE("szDataDescr: %s\n",debugstr_w(*ppszDataDescr));
        }
        TRACE_DATA_BLOB(pDataOut);
    }

    TRACE("returning %s\n", rc ? "ok" : "FAIL");

    return rc;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -