Commit 9d1ae850 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

crypt32: Add support for importing RSA public keys with BCrypt.

parent c2c79466
...@@ -2689,11 +2689,94 @@ done: ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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]);
......
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