crypt32: Add support for importing RSA public keys with BCrypt.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50925
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
(cherry picked from commit 9d1ae850df
)
Signed-off-by: Michael Stefaniuc <mstefani@winehq.org>
This commit is contained in:
parent
fa4714e604
commit
d54b02e281
|
@ -2689,11 +2689,94 @@ done:
|
||||||
return !status;
|
return !status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL CNG_ImportRSAPubKey(CERT_PUBLIC_KEY_INFO *info, BCRYPT_KEY_HANDLE *key)
|
||||||
|
{
|
||||||
|
DWORD size, modulus_len, i;
|
||||||
|
BLOBHEADER *hdr;
|
||||||
|
RSAPUBKEY *rsapubkey;
|
||||||
|
const WCHAR *rsa_algo;
|
||||||
|
BCRYPT_ALG_HANDLE alg = NULL;
|
||||||
|
BCRYPT_RSAKEY_BLOB *rsakey;
|
||||||
|
BYTE *s, *d;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
if (!info->PublicKey.cbData)
|
||||||
|
{
|
||||||
|
SetLastError(NTE_BAD_ALGID);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CryptDecodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, info->PublicKey.pbData,
|
||||||
|
info->PublicKey.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &hdr, &size))
|
||||||
|
{
|
||||||
|
WARN("CryptDecodeObjectEx failed\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->aiKeyAlg == CALG_RSA_KEYX)
|
||||||
|
rsa_algo = BCRYPT_RSA_ALGORITHM;
|
||||||
|
else if (hdr->aiKeyAlg == CALG_RSA_SIGN)
|
||||||
|
rsa_algo = BCRYPT_RSA_SIGN_ALGORITHM;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FIXME("Unsupported RSA algorithm: %#x\n", hdr->aiKeyAlg);
|
||||||
|
CryptMemFree(hdr);
|
||||||
|
SetLastError(NTE_BAD_ALGID);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status = BCryptOpenAlgorithmProvider(&alg, rsa_algo, NULL, 0)))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
rsapubkey = (RSAPUBKEY *)(hdr + 1);
|
||||||
|
|
||||||
|
modulus_len = size - sizeof(*hdr) - sizeof(*rsapubkey);
|
||||||
|
if (modulus_len != rsapubkey->bitlen / 8)
|
||||||
|
FIXME("RSA pubkey has wrong modulus_len %u\n", modulus_len);
|
||||||
|
|
||||||
|
size = sizeof(*rsakey) + sizeof(ULONG) + modulus_len;
|
||||||
|
|
||||||
|
if (!(rsakey = CryptMemAlloc(size)))
|
||||||
|
{
|
||||||
|
status = STATUS_NO_MEMORY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
rsakey->Magic = BCRYPT_RSAPUBLIC_MAGIC;
|
||||||
|
rsakey->BitLength = rsapubkey->bitlen;
|
||||||
|
rsakey->cbPublicExp = sizeof(ULONG);
|
||||||
|
rsakey->cbModulus = modulus_len;
|
||||||
|
rsakey->cbPrime1 = 0;
|
||||||
|
rsakey->cbPrime2 = 0;
|
||||||
|
|
||||||
|
d = (BYTE *)(rsakey + 1);
|
||||||
|
/* According to MSDN modulus and pubexp are in LE while
|
||||||
|
* BCRYPT_RSAKEY_BLOB is supposed to have them in BE format */
|
||||||
|
*(ULONG *)d = RtlUlongByteSwap(rsapubkey->pubexp);
|
||||||
|
d += sizeof(ULONG);
|
||||||
|
s = (BYTE *)(rsapubkey + 1);
|
||||||
|
for (i = 0; i < modulus_len; i++)
|
||||||
|
d[i] = s[modulus_len - i - 1];
|
||||||
|
|
||||||
|
status = BCryptImportKeyPair(alg, NULL, BCRYPT_RSAPUBLIC_BLOB, key, (BYTE *)rsakey, size, 0);
|
||||||
|
CryptMemFree(rsakey);
|
||||||
|
|
||||||
|
done:
|
||||||
|
CryptMemFree(hdr);
|
||||||
|
if (alg) BCryptCloseAlgorithmProvider(alg, 0);
|
||||||
|
if (status) SetLastError(RtlNtStatusToDosError(status));
|
||||||
|
return !status;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL CNG_ImportPubKey(CERT_PUBLIC_KEY_INFO *pubKeyInfo, BCRYPT_KEY_HANDLE *key)
|
BOOL CNG_ImportPubKey(CERT_PUBLIC_KEY_INFO *pubKeyInfo, BCRYPT_KEY_HANDLE *key)
|
||||||
{
|
{
|
||||||
if (!strcmp(pubKeyInfo->Algorithm.pszObjId, szOID_ECC_PUBLIC_KEY))
|
if (!strcmp(pubKeyInfo->Algorithm.pszObjId, szOID_ECC_PUBLIC_KEY))
|
||||||
return CNG_ImportECCPubKey(pubKeyInfo, key);
|
return CNG_ImportECCPubKey(pubKeyInfo, key);
|
||||||
|
|
||||||
|
|
||||||
|
if (!strcmp(pubKeyInfo->Algorithm.pszObjId, szOID_RSA_RSA))
|
||||||
|
return CNG_ImportRSAPubKey(pubKeyInfo, key);
|
||||||
|
|
||||||
FIXME("Unsupported public key type: %s\n", debugstr_a(pubKeyInfo->Algorithm.pszObjId));
|
FIXME("Unsupported public key type: %s\n", debugstr_a(pubKeyInfo->Algorithm.pszObjId));
|
||||||
SetLastError(NTE_BAD_ALGID);
|
SetLastError(NTE_BAD_ALGID);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
|
static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
|
||||||
static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
|
static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
|
||||||
|
static DWORD (WINAPI *pBCryptDestroyKey)(BCRYPT_KEY_HANDLE);
|
||||||
|
|
||||||
struct encodedInt
|
struct encodedInt
|
||||||
{
|
{
|
||||||
|
@ -8400,6 +8401,7 @@ static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
|
||||||
{
|
{
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
HCRYPTKEY key;
|
HCRYPTKEY key;
|
||||||
|
BCRYPT_KEY_HANDLE key2;
|
||||||
PCCERT_CONTEXT context;
|
PCCERT_CONTEXT context;
|
||||||
DWORD dwSize;
|
DWORD dwSize;
|
||||||
ALG_ID ai;
|
ALG_ID ai;
|
||||||
|
@ -8469,6 +8471,12 @@ static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
|
||||||
&context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
|
&context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
|
||||||
ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
|
ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
|
||||||
CryptDestroyKey(key);
|
CryptDestroyKey(key);
|
||||||
|
|
||||||
|
ret = CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING,
|
||||||
|
&context->pCertInfo->SubjectPublicKeyInfo, 0, NULL, &key2);
|
||||||
|
ok(ret, "CryptImportPublicKeyInfoEx2 failed: %08x\n", GetLastError());
|
||||||
|
if (pBCryptDestroyKey) pBCryptDestroyKey(key2);
|
||||||
|
|
||||||
CertFreeCertificateContext(context);
|
CertFreeCertificateContext(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8502,7 +8510,7 @@ 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,
|
||||||
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
|
||||||
HMODULE hCrypt32;
|
HMODULE hCrypt32, hBcrypt;
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
|
||||||
hCrypt32 = GetModuleHandleA("crypt32.dll");
|
hCrypt32 = GetModuleHandleA("crypt32.dll");
|
||||||
|
@ -8514,6 +8522,9 @@ START_TEST(encode)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hBcrypt = GetModuleHandleA("bcrypt.dll");
|
||||||
|
pBCryptDestroyKey = (void*)GetProcAddress(hBcrypt, "BCryptDestroyKey");
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(encodings); i++)
|
for (i = 0; i < ARRAY_SIZE(encodings); i++)
|
||||||
{
|
{
|
||||||
test_encodeInt(encodings[i]);
|
test_encodeInt(encodings[i]);
|
||||||
|
|
Loading…
Reference in New Issue