Implement CryptImport/ExportPublicKeyInfo.
This commit is contained in:
parent
531894148d
commit
d6a89fbae3
|
@ -98,8 +98,8 @@
|
|||
@ stub CryptEnumOIDInfo
|
||||
@ stub CryptEnumProvidersU
|
||||
@ stub CryptExportPKCS8
|
||||
@ stub CryptExportPublicKeyInfo
|
||||
@ stub CryptExportPublicKeyInfoEx
|
||||
@ stdcall CryptExportPublicKeyInfo(long long long ptr ptr)
|
||||
@ stdcall CryptExportPublicKeyInfoEx(long long long str long ptr ptr ptr)
|
||||
@ stub CryptFindOIDInfo
|
||||
@ stub CryptFormatObject
|
||||
@ stub CryptFreeOIDFunctionAddress
|
||||
|
@ -115,8 +115,8 @@
|
|||
@ stub CryptHashPublicKeyInfo
|
||||
@ stub CryptHashToBeSigned
|
||||
@ stub CryptImportPKCS8
|
||||
@ stub CryptImportPublicKeyInfo
|
||||
@ stub CryptImportPublicKeyInfoEx
|
||||
@ stdcall CryptImportPublicKeyInfo(long long ptr ptr)
|
||||
@ stdcall CryptImportPublicKeyInfoEx(long long ptr long long ptr ptr)
|
||||
@ stdcall CryptInitOIDFunctionSet(str long)
|
||||
@ stub CryptInstallOIDFunctionAddress
|
||||
@ stub CryptLoadSip
|
||||
|
|
|
@ -2352,6 +2352,8 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
}
|
||||
else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
|
||||
encodeFunc = CRYPT_AsnEncodeExtensions;
|
||||
else if (!strcmp(lpszStructType, szOID_RSA_RSA))
|
||||
encodeFunc = CRYPT_AsnEncodeRsaPubKey;
|
||||
else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
|
||||
encodeFunc = CRYPT_AsnEncodeUtcTime;
|
||||
else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
|
||||
|
@ -5438,6 +5440,8 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
}
|
||||
else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
|
||||
decodeFunc = CRYPT_AsnDecodeExtensions;
|
||||
else if (!strcmp(lpszStructType, szOID_RSA_RSA))
|
||||
decodeFunc = CRYPT_AsnDecodeRsaPubKey;
|
||||
else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
|
||||
decodeFunc = CRYPT_AsnDecodeUtcTime;
|
||||
else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
|
||||
|
@ -5473,3 +5477,128 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
FreeLibrary(lib);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
|
||||
DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
|
||||
{
|
||||
return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
|
||||
NULL, 0, NULL, pInfo, pcbInfo);
|
||||
}
|
||||
|
||||
BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
|
||||
DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
|
||||
void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
|
||||
{
|
||||
BOOL ret;
|
||||
HCRYPTKEY key;
|
||||
|
||||
TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv, dwKeySpec,
|
||||
dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
|
||||
pInfo, pcbInfo);
|
||||
|
||||
if (!hCryptProv)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pszPublicKeyObjId)
|
||||
pszPublicKeyObjId = szOID_RSA_RSA;
|
||||
if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
|
||||
{
|
||||
DWORD keySize = 0;
|
||||
|
||||
ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
|
||||
if (ret)
|
||||
{
|
||||
LPBYTE pubKey = HeapAlloc(GetProcessHeap(), 0, keySize);
|
||||
|
||||
if (pubKey)
|
||||
{
|
||||
ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
|
||||
&keySize);
|
||||
if (ret)
|
||||
{
|
||||
DWORD encodedLen = 0;
|
||||
|
||||
ret = CryptEncodeObject(dwCertEncodingType,
|
||||
pszPublicKeyObjId, pubKey, NULL, &encodedLen);
|
||||
if (ret)
|
||||
{
|
||||
DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
|
||||
strlen(pszPublicKeyObjId) + 1 + encodedLen;
|
||||
|
||||
if (!pInfo)
|
||||
*pcbInfo = sizeNeeded;
|
||||
else if (*pcbInfo < sizeNeeded)
|
||||
{
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
*pcbInfo = sizeNeeded;
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pInfo->Algorithm.pszObjId = (char *)pInfo +
|
||||
sizeof(CERT_PUBLIC_KEY_INFO);
|
||||
lstrcpyA(pInfo->Algorithm.pszObjId,
|
||||
pszPublicKeyObjId);
|
||||
pInfo->Algorithm.Parameters.cbData = 0;
|
||||
pInfo->Algorithm.Parameters.pbData = NULL;
|
||||
pInfo->PublicKey.pbData = (BYTE *)pInfo->Algorithm.pszObjId
|
||||
+ lstrlenA(pInfo->Algorithm.pszObjId) + 1;
|
||||
pInfo->PublicKey.cbData = encodedLen;
|
||||
pInfo->PublicKey.cUnusedBits = 0;
|
||||
ret = CryptEncodeObject(dwCertEncodingType,
|
||||
pszPublicKeyObjId, pubKey, pInfo->PublicKey.pbData,
|
||||
&pInfo->PublicKey.cbData);
|
||||
}
|
||||
}
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, pubKey);
|
||||
}
|
||||
else
|
||||
ret = FALSE;
|
||||
}
|
||||
CryptDestroyKey(key);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
|
||||
DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
|
||||
{
|
||||
return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
|
||||
0, 0, NULL, phKey);
|
||||
}
|
||||
|
||||
BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
|
||||
DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
|
||||
DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
|
||||
{
|
||||
BOOL ret;
|
||||
DWORD pubKeySize = 0;
|
||||
|
||||
TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv,
|
||||
dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
|
||||
|
||||
ret = CryptDecodeObject(dwCertEncodingType, pInfo->Algorithm.pszObjId,
|
||||
pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
|
||||
if (ret)
|
||||
{
|
||||
LPBYTE pubKey = HeapAlloc(GetProcessHeap(), 0, pubKeySize);
|
||||
|
||||
if (pubKey)
|
||||
{
|
||||
ret = CryptDecodeObject(dwCertEncodingType,
|
||||
pInfo->Algorithm.pszObjId, pInfo->PublicKey.pbData,
|
||||
pInfo->PublicKey.cbData, 0, pubKey, &pubKeySize);
|
||||
if (ret)
|
||||
ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
|
||||
phKey);
|
||||
HeapFree(GetProcessHeap(), 0, pubKey);
|
||||
}
|
||||
else
|
||||
ret = FALSE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -2470,6 +2470,114 @@ static void test_registerOIDFunction(void)
|
|||
ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
|
||||
}
|
||||
|
||||
/* Free *pInfo with HeapFree */
|
||||
static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
|
||||
{
|
||||
BOOL ret;
|
||||
DWORD size = 0;
|
||||
HCRYPTKEY key;
|
||||
|
||||
/* This crashes
|
||||
ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
|
||||
*/
|
||||
ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
|
||||
ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
|
||||
&size);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
|
||||
ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
|
||||
NULL, &size);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
|
||||
ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
|
||||
0, NULL, NULL, &size);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
|
||||
/* Test with no key */
|
||||
ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
|
||||
0, NULL, NULL, &size);
|
||||
ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08lx\n",
|
||||
GetLastError());
|
||||
ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
|
||||
ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
|
||||
NULL, 0, NULL, NULL, &size);
|
||||
ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n", GetLastError());
|
||||
*pInfo = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if (*pInfo)
|
||||
{
|
||||
ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
|
||||
X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
|
||||
ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n",
|
||||
GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
/* By default (we passed NULL as the OID) the OID is
|
||||
* szOID_RSA_RSA.
|
||||
*/
|
||||
ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
|
||||
"Expected %s, got %s\n", szOID_RSA_RSA,
|
||||
(*pInfo)->Algorithm.pszObjId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
|
||||
{
|
||||
BOOL ret;
|
||||
HCRYPTKEY key;
|
||||
|
||||
/* These crash
|
||||
ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
|
||||
ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
|
||||
ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
|
||||
ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
|
||||
NULL);
|
||||
*/
|
||||
ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
|
||||
ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
|
||||
ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
|
||||
&key);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
|
||||
ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
|
||||
&key);
|
||||
ok(ret, "CryptImportPublicKeyInfoEx failed: %08lx\n", GetLastError());
|
||||
CryptDestroyKey(key);
|
||||
}
|
||||
|
||||
static const char cspName[] = "WineCryptTemp";
|
||||
|
||||
static void testPortPublicKeyInfo(void)
|
||||
{
|
||||
HCRYPTPROV csp;
|
||||
BOOL ret;
|
||||
PCERT_PUBLIC_KEY_INFO info = NULL;
|
||||
|
||||
/* Just in case a previous run failed, delete this thing */
|
||||
CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
|
||||
CRYPT_DELETEKEYSET);
|
||||
ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
|
||||
CRYPT_NEWKEYSET);
|
||||
|
||||
testExportPublicKey(csp, &info);
|
||||
testImportPublicKey(csp, info);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, info);
|
||||
CryptReleaseContext(csp, 0);
|
||||
ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
|
||||
CRYPT_DELETEKEYSET);
|
||||
}
|
||||
|
||||
START_TEST(encode)
|
||||
{
|
||||
static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
|
||||
|
@ -2510,4 +2618,5 @@ START_TEST(encode)
|
|||
test_decodeCRLToBeSigned(encodings[i]);
|
||||
}
|
||||
test_registerOIDFunction();
|
||||
testPortPublicKeyInfo();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue