[PATCH 2/2] crypt32: Add support for importing RSA public keys with BCrypt.
Dmitry Timoshkov
dmitry at baikal.ru
Fri Apr 9 12:56:49 CDT 2021
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50925
Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
dlls/crypt32/cert.c | 71 +++++++++++++++++++++++++++++++++++++
dlls/crypt32/tests/encode.c | 13 ++++++-
2 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c
index 95e2746a7d5..b8c3d0b8dba 100644
--- a/dlls/crypt32/cert.c
+++ b/dlls/crypt32/cert.c
@@ -2689,11 +2689,82 @@ done:
return !status;
}
+static BOOL CNG_ImportRSAPubKey(CERT_PUBLIC_KEY_INFO *info, BCRYPT_KEY_HANDLE *key)
+{
+ DWORD rsakey_len, size;
+ BLOBHEADER *hdr;
+ RSAPUBKEY *rsapubkey;
+ const WCHAR *rsa_algo;
+ BCRYPT_ALG_HANDLE alg = NULL;
+ BCRYPT_RSAKEY_BLOB *rsakey;
+ 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;
+
+ rsakey_len = sizeof(*rsakey) + size;
+
+ if (!(rsakey = CryptMemAlloc(rsakey_len)))
+ {
+ status = STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ rsapubkey = (RSAPUBKEY *)(hdr + 1);
+
+ rsakey->Magic = BCRYPT_RSAPUBLIC_MAGIC;
+ rsakey->BitLength = rsapubkey->bitlen;
+ rsakey->cbPublicExp = size - rsapubkey->bitlen / 8;
+ rsakey->cbModulus = rsapubkey->bitlen / 8;
+ rsakey->cbPrime1 = 0;
+ rsakey->cbPrime2 = 0;
+
+ memcpy(rsakey + 1, rsapubkey, size);
+
+ status = BCryptImportKeyPair(alg, NULL, BCRYPT_RSAPUBLIC_BLOB, key, (BYTE *)rsakey, rsakey_len, 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)
{
if (!strcmp(pubKeyInfo->Algorithm.pszObjId, szOID_ECC_PUBLIC_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));
SetLastError(NTE_BAD_ALGID);
return FALSE;
diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c
index 38d2f84db14..7c72eba1b9b 100644
--- a/dlls/crypt32/tests/encode.c
+++ b/dlls/crypt32/tests/encode.c
@@ -30,6 +30,7 @@
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 DWORD (WINAPI *pBCryptDestroyKey)(BCRYPT_KEY_HANDLE);
struct encodedInt
{
@@ -8400,6 +8401,7 @@ static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
{
BOOL ret;
HCRYPTKEY key;
+ BCRYPT_KEY_HANDLE key2;
PCCERT_CONTEXT context;
DWORD dwSize;
ALG_ID ai;
@@ -8469,6 +8471,12 @@ static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
&context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
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);
}
}
@@ -8502,7 +8510,7 @@ START_TEST(encode)
{
static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
- HMODULE hCrypt32;
+ HMODULE hCrypt32, hBcrypt;
DWORD i;
hCrypt32 = GetModuleHandleA("crypt32.dll");
@@ -8514,6 +8522,9 @@ START_TEST(encode)
return;
}
+ hBcrypt = GetModuleHandleA("bcrypt.dll");
+ pBCryptDestroyKey = (void*)GetProcAddress(hBcrypt, "BCryptDestroyKey");
+
for (i = 0; i < ARRAY_SIZE(encodings); i++)
{
test_encodeInt(encodings[i]);
--
2.30.2
More information about the wine-devel
mailing list