Implement CryptImport/ExportPublicKeyInfo.
This commit is contained in:
parent
531894148d
commit
d6a89fbae3
|
@ -98,8 +98,8 @@
|
||||||
@ stub CryptEnumOIDInfo
|
@ stub CryptEnumOIDInfo
|
||||||
@ stub CryptEnumProvidersU
|
@ stub CryptEnumProvidersU
|
||||||
@ stub CryptExportPKCS8
|
@ stub CryptExportPKCS8
|
||||||
@ stub CryptExportPublicKeyInfo
|
@ stdcall CryptExportPublicKeyInfo(long long long ptr ptr)
|
||||||
@ stub CryptExportPublicKeyInfoEx
|
@ stdcall CryptExportPublicKeyInfoEx(long long long str long ptr ptr ptr)
|
||||||
@ stub CryptFindOIDInfo
|
@ stub CryptFindOIDInfo
|
||||||
@ stub CryptFormatObject
|
@ stub CryptFormatObject
|
||||||
@ stub CryptFreeOIDFunctionAddress
|
@ stub CryptFreeOIDFunctionAddress
|
||||||
|
@ -115,8 +115,8 @@
|
||||||
@ stub CryptHashPublicKeyInfo
|
@ stub CryptHashPublicKeyInfo
|
||||||
@ stub CryptHashToBeSigned
|
@ stub CryptHashToBeSigned
|
||||||
@ stub CryptImportPKCS8
|
@ stub CryptImportPKCS8
|
||||||
@ stub CryptImportPublicKeyInfo
|
@ stdcall CryptImportPublicKeyInfo(long long ptr ptr)
|
||||||
@ stub CryptImportPublicKeyInfoEx
|
@ stdcall CryptImportPublicKeyInfoEx(long long ptr long long ptr ptr)
|
||||||
@ stdcall CryptInitOIDFunctionSet(str long)
|
@ stdcall CryptInitOIDFunctionSet(str long)
|
||||||
@ stub CryptInstallOIDFunctionAddress
|
@ stub CryptInstallOIDFunctionAddress
|
||||||
@ stub CryptLoadSip
|
@ stub CryptLoadSip
|
||||||
|
|
|
@ -2352,6 +2352,8 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
||||||
}
|
}
|
||||||
else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
|
else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
|
||||||
encodeFunc = CRYPT_AsnEncodeExtensions;
|
encodeFunc = CRYPT_AsnEncodeExtensions;
|
||||||
|
else if (!strcmp(lpszStructType, szOID_RSA_RSA))
|
||||||
|
encodeFunc = CRYPT_AsnEncodeRsaPubKey;
|
||||||
else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
|
else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
|
||||||
encodeFunc = CRYPT_AsnEncodeUtcTime;
|
encodeFunc = CRYPT_AsnEncodeUtcTime;
|
||||||
else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
|
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))
|
else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
|
||||||
decodeFunc = CRYPT_AsnDecodeExtensions;
|
decodeFunc = CRYPT_AsnDecodeExtensions;
|
||||||
|
else if (!strcmp(lpszStructType, szOID_RSA_RSA))
|
||||||
|
decodeFunc = CRYPT_AsnDecodeRsaPubKey;
|
||||||
else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
|
else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
|
||||||
decodeFunc = CRYPT_AsnDecodeUtcTime;
|
decodeFunc = CRYPT_AsnDecodeUtcTime;
|
||||||
else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
|
else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
|
||||||
|
@ -5473,3 +5477,128 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
||||||
FreeLibrary(lib);
|
FreeLibrary(lib);
|
||||||
return ret;
|
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());
|
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)
|
START_TEST(encode)
|
||||||
{
|
{
|
||||||
static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
|
static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
|
||||||
|
@ -2510,4 +2618,5 @@ START_TEST(encode)
|
||||||
test_decodeCRLToBeSigned(encodings[i]);
|
test_decodeCRLToBeSigned(encodings[i]);
|
||||||
}
|
}
|
||||||
test_registerOIDFunction();
|
test_registerOIDFunction();
|
||||||
|
testPortPublicKeyInfo();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue