rsaenh: Honor a key's permissions when exporting a private key.
This commit is contained in:
parent
8265569e99
commit
e8ea6700ca
|
@ -311,13 +311,12 @@ RSAENH_CPDestroyHash(
|
||||||
HCRYPTHASH hHash
|
HCRYPTHASH hHash
|
||||||
);
|
);
|
||||||
|
|
||||||
BOOL WINAPI
|
static BOOL crypt_export_key(
|
||||||
RSAENH_CPExportKey(
|
CRYPTKEY *pCryptKey,
|
||||||
HCRYPTPROV hProv,
|
|
||||||
HCRYPTKEY hKey,
|
|
||||||
HCRYPTKEY hPubKey,
|
HCRYPTKEY hPubKey,
|
||||||
DWORD dwBlobType,
|
DWORD dwBlobType,
|
||||||
DWORD dwFlags,
|
DWORD dwFlags,
|
||||||
|
BOOL force,
|
||||||
BYTE *pbData,
|
BYTE *pbData,
|
||||||
DWORD *pdwDataLen
|
DWORD *pdwDataLen
|
||||||
);
|
);
|
||||||
|
@ -911,14 +910,13 @@ static void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, LPCSTR szValueName, D
|
||||||
if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
|
if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
|
||||||
(OBJECTHDR**)&pKey))
|
(OBJECTHDR**)&pKey))
|
||||||
{
|
{
|
||||||
if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0, PRIVATEKEYBLOB, 0, 0,
|
if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, 0, &dwLen))
|
||||||
&dwLen))
|
|
||||||
{
|
{
|
||||||
pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
|
pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
|
||||||
if (pbKey)
|
if (pbKey)
|
||||||
{
|
{
|
||||||
if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0,
|
if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, pbKey,
|
||||||
PRIVATEKEYBLOB, 0, pbKey, &dwLen))
|
&dwLen))
|
||||||
{
|
{
|
||||||
blobIn.pbData = pbKey;
|
blobIn.pbData = pbKey;
|
||||||
blobIn.cbData = dwLen;
|
blobIn.cbData = dwLen;
|
||||||
|
@ -2282,8 +2280,8 @@ static BOOL crypt_export_public_key(CRYPTKEY *pCryptKey, BYTE *pbData,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BYTE *pbData,
|
static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BOOL force,
|
||||||
DWORD *pdwDataLen)
|
BYTE *pbData, DWORD *pdwDataLen)
|
||||||
{
|
{
|
||||||
BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
|
BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
|
||||||
RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
|
RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
|
||||||
|
@ -2293,6 +2291,11 @@ static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BYTE *pbData,
|
||||||
SetLastError(NTE_BAD_KEY);
|
SetLastError(NTE_BAD_KEY);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
if (!force && !(pCryptKey->dwPermissions & CRYPT_EXPORT))
|
||||||
|
{
|
||||||
|
SetLastError(NTE_BAD_KEY_STATE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
|
dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
|
||||||
2 * pCryptKey->dwKeyLen + 5 * ((pCryptKey->dwKeyLen + 1) >> 1);
|
2 * pCryptKey->dwKeyLen + 5 * ((pCryptKey->dwKeyLen + 1) >> 1);
|
||||||
|
@ -2318,6 +2321,67 @@ static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BYTE *pbData,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* crypt_export_key [Internal]
|
||||||
|
*
|
||||||
|
* Export a key into a binary large object (BLOB). Called by CPExportKey and
|
||||||
|
* by store_key_pair.
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* pCryptKey [I] Key to be exported.
|
||||||
|
* hPubKey [I] Key used to encrypt sensitive BLOB data.
|
||||||
|
* dwBlobType [I] SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB.
|
||||||
|
* dwFlags [I] Currently none defined.
|
||||||
|
* force [I] If TRUE, the key is written no matter what the key's
|
||||||
|
* permissions are. Otherwise the key's permissions are
|
||||||
|
* checked before exporting.
|
||||||
|
* pbData [O] Pointer to a buffer where the BLOB will be written to.
|
||||||
|
* pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: TRUE.
|
||||||
|
* Failure: FALSE.
|
||||||
|
*/
|
||||||
|
static BOOL crypt_export_key(CRYPTKEY *pCryptKey, HCRYPTKEY hPubKey,
|
||||||
|
DWORD dwBlobType, DWORD dwFlags, BOOL force,
|
||||||
|
BYTE *pbData, DWORD *pdwDataLen)
|
||||||
|
{
|
||||||
|
CRYPTKEY *pPubKey;
|
||||||
|
|
||||||
|
if (dwFlags & CRYPT_SSL2_FALLBACK) {
|
||||||
|
if (pCryptKey->aiAlgid != CALG_SSL2_MASTER) {
|
||||||
|
SetLastError(NTE_BAD_KEY);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((BYTE)dwBlobType)
|
||||||
|
{
|
||||||
|
case SIMPLEBLOB:
|
||||||
|
if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey)){
|
||||||
|
SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error_code? */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return crypt_export_simple(pCryptKey, pPubKey, dwFlags, pbData,
|
||||||
|
pdwDataLen);
|
||||||
|
|
||||||
|
case PUBLICKEYBLOB:
|
||||||
|
if (is_valid_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY)) {
|
||||||
|
SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return crypt_export_public_key(pCryptKey, pbData, pdwDataLen);
|
||||||
|
|
||||||
|
case PRIVATEKEYBLOB:
|
||||||
|
return crypt_export_private_key(pCryptKey, force, pbData, pdwDataLen);
|
||||||
|
|
||||||
|
default:
|
||||||
|
SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* CPExportKey (RSAENH.@)
|
* CPExportKey (RSAENH.@)
|
||||||
*
|
*
|
||||||
|
@ -2339,7 +2403,7 @@ static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BYTE *pbData,
|
||||||
BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey,
|
BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey,
|
||||||
DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
|
DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
|
||||||
{
|
{
|
||||||
CRYPTKEY *pCryptKey, *pPubKey;
|
CRYPTKEY *pCryptKey;
|
||||||
|
|
||||||
TRACE("(hProv=%08lx, hKey=%08lx, hPubKey=%08lx, dwBlobType=%08x, dwFlags=%08x, pbData=%p,"
|
TRACE("(hProv=%08lx, hKey=%08lx, hPubKey=%08lx, dwBlobType=%08x, dwFlags=%08x, pbData=%p,"
|
||||||
"pdwDataLen=%p)\n", hProv, hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen);
|
"pdwDataLen=%p)\n", hProv, hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen);
|
||||||
|
@ -2356,37 +2420,8 @@ BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubK
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwFlags & CRYPT_SSL2_FALLBACK) {
|
return crypt_export_key(pCryptKey, hPubKey, dwBlobType, dwFlags, FALSE,
|
||||||
if (pCryptKey->aiAlgid != CALG_SSL2_MASTER) {
|
pbData, pdwDataLen);
|
||||||
SetLastError(NTE_BAD_KEY);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ((BYTE)dwBlobType)
|
|
||||||
{
|
|
||||||
case SIMPLEBLOB:
|
|
||||||
if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey)){
|
|
||||||
SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error_code? */
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return crypt_export_simple(pCryptKey, pPubKey, dwFlags, pbData, pdwDataLen);
|
|
||||||
|
|
||||||
case PUBLICKEYBLOB:
|
|
||||||
if (is_valid_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY)) {
|
|
||||||
SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return crypt_export_public_key(pCryptKey, pbData, pdwDataLen);
|
|
||||||
|
|
||||||
case PRIVATEKEYBLOB:
|
|
||||||
return crypt_export_private_key(pCryptKey, pbData, pdwDataLen);
|
|
||||||
|
|
||||||
default:
|
|
||||||
SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
|
|
@ -1574,7 +1574,6 @@ static void test_rsa_encrypt(void)
|
||||||
/* but its private key may not be. */
|
/* but its private key may not be. */
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
|
result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
|
||||||
todo_wine
|
|
||||||
ok(!result && GetLastError() == NTE_BAD_KEY_STATE,
|
ok(!result && GetLastError() == NTE_BAD_KEY_STATE,
|
||||||
"expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
|
"expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
|
||||||
/* Setting the permissions of the key exchange key isn't allowed, either. */
|
/* Setting the permissions of the key exchange key isn't allowed, either. */
|
||||||
|
@ -1606,7 +1605,6 @@ static void test_rsa_encrypt(void)
|
||||||
/* but its private key may not be. */
|
/* but its private key may not be. */
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
|
result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
|
||||||
todo_wine
|
|
||||||
ok(!result && GetLastError() == NTE_BAD_KEY_STATE,
|
ok(!result && GetLastError() == NTE_BAD_KEY_STATE,
|
||||||
"expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
|
"expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
|
||||||
/* Setting the permissions of the signature key isn't allowed, either. */
|
/* Setting the permissions of the signature key isn't allowed, either. */
|
||||||
|
|
Loading…
Reference in New Issue