crypt32: Implement PKCS_RSA_PRIVATE_KEY decoding.
This commit is contained in:
parent
0c7ebefd67
commit
7fb8ee1995
|
@ -3936,6 +3936,147 @@ static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
|
||||||
return ret;
|
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,
|
static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
|
||||||
DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
|
DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
|
||||||
DWORD *pcbDecoded)
|
DWORD *pcbDecoded)
|
||||||
|
@ -5798,6 +5939,9 @@ static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
|
||||||
case LOWORD(RSA_CSP_PUBLICKEYBLOB):
|
case LOWORD(RSA_CSP_PUBLICKEYBLOB):
|
||||||
decodeFunc = CRYPT_AsnDecodeRsaPubKey;
|
decodeFunc = CRYPT_AsnDecodeRsaPubKey;
|
||||||
break;
|
break;
|
||||||
|
case LOWORD(PKCS_RSA_PRIVATE_KEY):
|
||||||
|
decodeFunc = CRYPT_AsnDecodeRsaPrivKey;
|
||||||
|
break;
|
||||||
case LOWORD(X509_UNICODE_NAME):
|
case LOWORD(X509_UNICODE_NAME):
|
||||||
decodeFunc = CRYPT_AsnDecodeUnicodeName;
|
decodeFunc = CRYPT_AsnDecodeUnicodeName;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -8101,7 +8101,7 @@ static void test_decodeRsaPrivateKey(DWORD dwEncoding)
|
||||||
ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
|
ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
|
||||||
rsaPrivKeyDer, sizeof(rsaPrivKeyDer)-10,
|
rsaPrivKeyDer, sizeof(rsaPrivKeyDer)-10,
|
||||||
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
|
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",
|
"Expected CRYPT_E_ASN1_EOD, got %08x\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
|
|
||||||
|
@ -8110,7 +8110,7 @@ static void test_decodeRsaPrivateKey(DWORD dwEncoding)
|
||||||
ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
|
ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
|
||||||
rsaPrivKeyDer, sizeof(rsaPrivKeyDer),
|
rsaPrivKeyDer, sizeof(rsaPrivKeyDer),
|
||||||
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
|
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)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue