Commit d6a89fba authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

Implement CryptImport/ExportPublicKeyInfo.

parent 53189414
......@@ -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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment