peaAlgidInfo = get_algid_info(hProv, aiAlgid);
if (!peaAlgidInfo) return (HCRYPTKEY)INVALID_HANDLE_VALUE;
+ TRACE("alg = %s, dwKeyLen = %d\n", debugstr_a(peaAlgidInfo->szName),
+ dwKeyLen);
/*
* Assume the default key length, if none is specified explicitly
*/
dwKeyLen > peaAlgidInfo->dwMaxLen ||
dwKeyLen < peaAlgidInfo->dwMinLen)
{
- SetLastError(NTE_BAD_FLAGS);
+ TRACE("key len %d out of bounds (%d, %d)\n", dwKeyLen,
+ peaAlgidInfo->dwMinLen, peaAlgidInfo->dwMaxLen);
+ SetLastError(NTE_BAD_DATA);
return (HCRYPTKEY)INVALID_HANDLE_VALUE;
}
}
store_key_container_permissions(pKeyContainer);
release_key_container_keys(pKeyContainer);
}
+ else
+ release_key_container_keys(pKeyContainer);
HeapFree( GetProcessHeap(), 0, pKeyContainer );
}
(OBJECTHDR**)&pKeyContainer))
return (HCRYPTPROV)INVALID_HANDLE_VALUE;
+ /* read_key_value calls import_key, which calls import_private_key,
+ * which implicitly installs the key value into the appropriate key
+ * container key. Thus the ref count is incremented twice, once for
+ * the output key value, and once for the implicit install, and needs
+ * to be decremented to balance the two.
+ */
if (read_key_value(hKeyContainer, hKey, AT_KEYEXCHANGE,
dwProtectFlags, &hCryptKey))
- pKeyContainer->hKeyExchangeKeyPair = hCryptKey;
+ release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY);
if (read_key_value(hKeyContainer, hKey, AT_SIGNATURE,
dwProtectFlags, &hCryptKey))
- pKeyContainer->hSignatureKeyPair = hCryptKey;
+ release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY);
}
return hKeyContainer;
if (Final) {
if (pbData[*pdwDataLen-1] &&
pbData[*pdwDataLen-1] <= pCryptKey->dwBlockLen &&
- pbData[*pdwDataLen-1] < *pdwDataLen) {
+ pbData[*pdwDataLen-1] <= *pdwDataLen) {
BOOL padOkay = TRUE;
/* check that every bad byte has the same value */
return TRUE;
}
+static BOOL crypt_export_plaintext_key(CRYPTKEY *pCryptKey, BYTE *pbData,
+ DWORD *pdwDataLen)
+{
+ BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
+ DWORD *pKeyLen = (DWORD*)(pBlobHeader+1);
+ BYTE *pbKey = (BYTE*)(pKeyLen+1);
+ DWORD dwDataLen;
+
+ dwDataLen = sizeof(BLOBHEADER) + sizeof(DWORD) + pCryptKey->dwKeyLen;
+ if (pbData) {
+ if (*pdwDataLen < dwDataLen) {
+ SetLastError(ERROR_MORE_DATA);
+ *pdwDataLen = dwDataLen;
+ return FALSE;
+ }
+
+ pBlobHeader->bType = PLAINTEXTKEYBLOB;
+ pBlobHeader->bVersion = CUR_BLOB_VERSION;
+ pBlobHeader->reserved = 0;
+ pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
+
+ *pKeyLen = pCryptKey->dwKeyLen;
+ memcpy(pbKey, &pCryptKey->abKeyValue, pCryptKey->dwKeyLen);
+ }
+ *pdwDataLen = dwDataLen;
+ return TRUE;
+}
/******************************************************************************
* crypt_export_key [Internal]
*
case PRIVATEKEYBLOB:
return crypt_export_private_key(pCryptKey, force, pbData, pdwDataLen);
+
+ case PLAINTEXTKEYBLOB:
+ return crypt_export_plaintext_key(pCryptKey, pbData, pdwDataLen);
default:
SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
return TRUE;
}
+/******************************************************************************
+ * import_plaintext_key [Internal]
+ *
+ * Import a plaintext key into a key container.
+ *
+ * PARAMS
+ * hProv [I] Key container into which the symmetric key is to be imported.
+ * pbData [I] Pointer to a buffer which holds the plaintext key BLOB.
+ * dwDataLen [I] Length of data in buffer at pbData.
+ * dwFlags [I] One of:
+ * CRYPT_EXPORTABLE: the imported key is marked exportable
+ * phKey [O] Handle to the imported key.
+ *
+ *
+ * NOTES
+ * Assumes the caller has already checked the BLOBHEADER at pbData to ensure
+ * it's a PLAINTEXTKEYBLOB.
+ *
+ * RETURNS
+ * Success: TRUE.
+ * Failure: FALSE.
+ */
+static BOOL import_plaintext_key(HCRYPTPROV hProv, CONST BYTE *pbData,
+ DWORD dwDataLen, DWORD dwFlags,
+ HCRYPTKEY *phKey)
+{
+ CRYPTKEY *pCryptKey;
+ CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
+ CONST DWORD *pKeyLen = (CONST DWORD *)(pBlobHeader + 1);
+ CONST BYTE *pbKeyStream = (CONST BYTE*)(pKeyLen + 1);
+
+ if (dwDataLen < sizeof(BLOBHEADER)+sizeof(DWORD)+*pKeyLen)
+ {
+ SetLastError(NTE_BAD_DATA); /* FIXME: error code */
+ return FALSE;
+ }
+
+ *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, *pKeyLen<<19, &pCryptKey);
+ if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
+ return FALSE;
+ memcpy(pCryptKey->abKeyValue, pbKeyStream, *pKeyLen);
+ setup_key(pCryptKey);
+ if (dwFlags & CRYPT_EXPORTABLE)
+ pCryptKey->dwPermissions |= CRYPT_EXPORT;
+ return TRUE;
+}
+
/******************************************************************************
* import_key [Internal]
*
pBlobHeader->bVersion != CUR_BLOB_VERSION ||
pBlobHeader->reserved != 0)
{
+ TRACE("bVersion = %d, reserved = %d\n", pBlobHeader->bVersion,
+ pBlobHeader->reserved);
SetLastError(NTE_BAD_DATA);
return FALSE;
}
* fStoreKey's original value.
*/
fStoreKey = fStoreKey && !(dwFlags & CRYPT_VERIFYCONTEXT);
+ TRACE("blob type: %x\n", pBlobHeader->bType);
switch (pBlobHeader->bType)
{
case PRIVATEKEYBLOB:
return import_symmetric_key(hProv, pbData, dwDataLen, hPubKey,
dwFlags, phKey);
+ case PLAINTEXTKEYBLOB:
+ return import_plaintext_key(hProv, pbData, dwDataLen, dwFlags,
+ phKey);
+
default:
SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
return FALSE;
TRACE("(hProv=%08lx, pbData=%p, dwDataLen=%d, hPubKey=%08lx, dwFlags=%08x, phKey=%p)\n",
hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
+ if (dwFlags & CRYPT_IPSEC_HMAC_KEY)
+ {
+ FIXME("unimplemented for CRYPT_IPSEC_HMAC_KEY\n");
+ SetLastError(NTE_BAD_FLAGS);
+ return FALSE;
+ }
return import_key(hProv, pbData, dwDataLen, hPubKey, dwFlags, TRUE, phKey);
}
if (pCryptKey) {
new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
setup_key(pCryptKey);
- if (Algid == AT_SIGNATURE) {
- RSAENH_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair);
- copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
- &pKeyContainer->hSignatureKeyPair);
- }
+ release_and_install_key(hProv, *phKey,
+ &pKeyContainer->hSignatureKeyPair,
+ FALSE);
}
break;
if (pCryptKey) {
new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
setup_key(pCryptKey);
- if (Algid == AT_KEYEXCHANGE) {
- RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
- copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
- &pKeyContainer->hKeyExchangeKeyPair);
- }
+ release_and_install_key(hProv, *phKey,
+ &pKeyContainer->hKeyExchangeKeyPair,
+ FALSE);
}
break;
LPCWSTR sDescription, DWORD dwFlags, BYTE *pbSignature,
DWORD *pdwSigLen)
{
- HCRYPTKEY hCryptKey;
+ HCRYPTKEY hCryptKey = (HCRYPTKEY)INVALID_HANDLE_VALUE;
CRYPTKEY *pCryptKey;
DWORD dwHashLen;
BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
ALG_ID aiAlgid;
+ BOOL ret = FALSE;
TRACE("(hProv=%08lx, hHash=%08lx, dwKeySpec=%08x, sDescription=%s, dwFlags=%08x, "
"pbSignature=%p, pdwSigLen=%p)\n", hProv, hHash, dwKeySpec, debugstr_w(sDescription),
(OBJECTHDR**)&pCryptKey))
{
SetLastError(NTE_NO_KEY);
- return FALSE;
+ goto out;
}
if (!pbSignature) {
*pdwSigLen = pCryptKey->dwKeyLen;
- return TRUE;
+ ret = TRUE;
+ goto out;
}
if (pCryptKey->dwKeyLen > *pdwSigLen)
{
SetLastError(ERROR_MORE_DATA);
*pdwSigLen = pCryptKey->dwKeyLen;
- return FALSE;
+ goto out;
}
*pdwSigLen = pCryptKey->dwKeyLen;
if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription,
(DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
{
- return FALSE;
+ goto out;
}
}
dwHashLen = sizeof(DWORD);
- if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) return FALSE;
+ if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) goto out;
dwHashLen = RSAENH_MAX_HASH_SIZE;
- if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) return FALSE;
+ if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) goto out;
if (!build_hash_signature(pbSignature, *pdwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) {
- return FALSE;
+ goto out;
}
- return encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbSignature, pbSignature, RSAENH_ENCRYPT);
+ ret = encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbSignature, pbSignature, RSAENH_ENCRYPT);
+out:
+ RSAENH_CPDestroyKey(hProv, hCryptKey);
+ return ret;
}
/******************************************************************************
{
static const WCHAR szName[] = { 'N','a','m','e',0 };
static const WCHAR szRSAName[3][54] = {
- { 'M','i','c','r','o','s','o','f','t',' ', 'B','a','s','e',' ',
+ { 'M','i','c','r','o','s','o','f','t',' ',
+ 'E','n','h','a','n','c','e','d',' ',
'C','r','y','p','t','o','g','r','a','p','h','i','c',' ',
'P','r','o','v','i','d','e','r',' ','v','1','.','0',0 },
{ 'M','i','c','r','o','s','o','f','t',' ','R','S','A',' ',