[2/2] crypt32: Implement PKCS_RSA_PRIVATE_KEY decoding.
Vincent Povirk
madewokherd at gmail.com
Thu Feb 26 15:00:17 CST 2015
-------------- next part --------------
From 397978657b6dc56115662766b067c81bf83cc9df Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Thu, 26 Feb 2015 14:48:05 -0600
Subject: [PATCH 2/2] crypt32: Implement PKCS_RSA_PRIVATE_KEY decoding.
---
dlls/crypt32/decode.c | 144 ++++++++++++++++++++++++++++++++++++++++++++
dlls/crypt32/tests/encode.c | 4 +-
2 files changed, 146 insertions(+), 2 deletions(-)
diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c
index e5f8baf..92dfba2 100644
--- a/dlls/crypt32/decode.c
+++ b/dlls/crypt32/decode.c
@@ -3936,6 +3936,147 @@ static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
return ret;
}
+#define RSA2_MAGIC 0x32415352
+
+struct DECODED_RSA_PRIV_KEY
+{
+ DWORD version;
+ DWORD pubexp;
+ CRYPT_INTEGER_BLOB modulus;
+ CRYPT_INTEGER_BLOB privexp;
+ CRYPT_INTEGER_BLOB prime1;
+ CRYPT_INTEGER_BLOB prime2;
+ CRYPT_INTEGER_BLOB exponent1;
+ CRYPT_INTEGER_BLOB exponent2;
+ CRYPT_INTEGER_BLOB coefficient;
+};
+
+static BOOL WINAPI CRYPT_AsnDecodeRsaPrivKey(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+ DWORD halflen;
+
+ __TRY
+ {
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, version),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, modulus),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, modulus.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, pubexp),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, privexp),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, privexp.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime1),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime1.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime2),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime2.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient.pbData),
+ 0 },
+ };
+ struct DECODED_RSA_PRIV_KEY *decodedKey = NULL;
+ DWORD size = 0;
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
+ &size, NULL, NULL);
+ if (ret)
+ {
+ halflen = decodedKey->modulus.cbData / 2;
+ if ((decodedKey->modulus.cbData != halflen * 2) ||
+ (decodedKey->prime1.cbData != halflen) ||
+ (decodedKey->prime2.cbData != halflen) ||
+ (decodedKey->exponent1.cbData != halflen) ||
+ (decodedKey->exponent2.cbData != halflen) ||
+ (decodedKey->coefficient.cbData != halflen) ||
+ (decodedKey->privexp.cbData != halflen * 2))
+ {
+ ret = FALSE;
+ SetLastError(CRYPT_E_BAD_ENCODE);
+ }
+
+ if (ret)
+ {
+ DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
+ (halflen * 9);
+
+ if (!pvStructInfo)
+ {
+ *pcbStructInfo = bytesNeeded;
+ ret = TRUE;
+ }
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ BLOBHEADER *hdr;
+ RSAPUBKEY *rsaPubKey;
+ BYTE *vardata;
+
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+
+ hdr = pvStructInfo;
+ hdr->bType = PRIVATEKEYBLOB;
+ hdr->bVersion = CUR_BLOB_VERSION;
+ hdr->reserved = 0;
+ hdr->aiKeyAlg = CALG_RSA_KEYX;
+
+ rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
+ sizeof(BLOBHEADER));
+ rsaPubKey->magic = RSA2_MAGIC;
+ rsaPubKey->pubexp = decodedKey->pubexp;
+ rsaPubKey->bitlen = halflen * 16;
+
+ vardata = (BYTE*)(rsaPubKey + 1);
+ memcpy(vardata,
+ decodedKey->modulus.pbData, halflen * 2);
+ memcpy(vardata + halflen * 2,
+ decodedKey->prime1.pbData, halflen);
+ memcpy(vardata + halflen * 3,
+ decodedKey->prime2.pbData, halflen);
+ memcpy(vardata + halflen * 4,
+ decodedKey->exponent1.pbData, halflen);
+ memcpy(vardata + halflen * 5,
+ decodedKey->exponent2.pbData, halflen);
+ memcpy(vardata + halflen * 6,
+ decodedKey->coefficient.pbData, halflen);
+ memcpy(vardata + halflen * 7,
+ decodedKey->privexp.pbData, halflen * 2);
+ }
+ }
+
+ LocalFree(decodedKey);
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
DWORD *pcbDecoded)
@@ -5798,6 +5939,9 @@ static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
case LOWORD(RSA_CSP_PUBLICKEYBLOB):
decodeFunc = CRYPT_AsnDecodeRsaPubKey;
break;
+ case LOWORD(PKCS_RSA_PRIVATE_KEY):
+ decodeFunc = CRYPT_AsnDecodeRsaPrivKey;
+ break;
case LOWORD(X509_UNICODE_NAME):
decodeFunc = CRYPT_AsnDecodeUnicodeName;
break;
diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c
index 3240a84..b45b5f2 100644
--- a/dlls/crypt32/tests/encode.c
+++ b/dlls/crypt32/tests/encode.c
@@ -8101,7 +8101,7 @@ static void test_decodeRsaPrivateKey(DWORD dwEncoding)
ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
rsaPrivKeyDer, sizeof(rsaPrivKeyDer)-10,
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
- todo_wine ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD),
+ ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD),
"Expected CRYPT_E_ASN1_EOD, got %08x\n",
GetLastError());
@@ -8110,7 +8110,7 @@ static void test_decodeRsaPrivateKey(DWORD dwEncoding)
ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
rsaPrivKeyDer, sizeof(rsaPrivKeyDer),
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
- todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
+ ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
--
2.1.0
More information about the wine-patches
mailing list