Commit 69dfea8f authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

Encode RSA public key modulus as unsigned integer, with tests.

parent f469b6f8
......@@ -115,6 +115,9 @@ static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
......@@ -165,6 +168,11 @@ static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
/* Like CRYPT_AsnDecodeInteger, but unsigned. */
static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, DWORD *pcbStructInfo);
/* filter for page-fault exceptions */
static WINE_EXCEPTION_FILTER(page_fault)
......@@ -1710,7 +1718,7 @@ static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
(BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
struct AsnEncodeSequenceItem items[] = {
{ &blob, CRYPT_AsnEncodeInteger, 0 },
{ &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
{ &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
};
......@@ -4385,7 +4393,7 @@ static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
{
struct AsnDecodeSequenceItem items[] = {
{ offsetof(struct DECODED_RSA_PUB_KEY, modulus),
CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
0 },
{ offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
......@@ -4801,56 +4809,94 @@ static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret;
__TRY
if (pbEncoded[0] == ASN_INTEGER)
{
if (pbEncoded[0] == ASN_INTEGER)
DWORD bytesNeeded, dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
DWORD bytesNeeded, dataLen;
CRYPT_INTEGER_BLOB *blob;
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if (*pcbStructInfo < bytesNeeded)
{
bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
pvStructInfo, pcbStructInfo, bytesNeeded)))
*pcbStructInfo = bytesNeeded;
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
else
{
CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
blob->cbData = dataLen;
assert(blob->pbData);
/* remove leading zero byte if it exists */
if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
{
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
blob->cbData--;
blob->pbData++;
}
if (blob->cbData)
{
DWORD i;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
blob->cbData = dataLen;
blob->pbData = (BYTE *)pvStructInfo +
sizeof(CRYPT_INTEGER_BLOB);
/* remove leading zero byte if it exists */
if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
{
blob->cbData--;
blob->pbData++;
}
if (blob->cbData)
for (i = 0; i < blob->cbData; i++)
{
DWORD i;
for (i = 0; i < blob->cbData; i++)
blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
pbEncoded[1] - i - 1);
blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
dataLen - i - 1);
}
}
}
}
else
}
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret;
__TRY
{
DWORD bytesNeeded;
if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
lpszStructType, pbEncoded, cbEncoded,
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
pvStructInfo, pcbStructInfo, bytesNeeded)))
{
CRYPT_INTEGER_BLOB *blob;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
blob->pbData = (BYTE *)pvStructInfo +
sizeof(CRYPT_INTEGER_BLOB);
ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
lpszStructType, pbEncoded, cbEncoded,
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
&bytesNeeded);
}
}
}
__EXCEPT(page_fault)
......
......@@ -1420,8 +1420,12 @@ static void test_decodeBasicConstraints(DWORD dwEncoding)
/* These are terrible public keys of course, I'm just testing encoding */
static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
struct EncodedRSAPubKey
{
......@@ -1434,6 +1438,8 @@ struct EncodedRSAPubKey
struct EncodedRSAPubKey rsaPubKeys[] = {
{ modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
{ modulus2, sizeof(modulus2), mod2_encoded, 5 },
{ modulus3, sizeof(modulus3), mod3_encoded, 5 },
{ modulus4, sizeof(modulus4), mod4_encoded, 8 },
};
static void test_encodeRsaPublicKey(DWORD dwEncoding)
......@@ -1443,7 +1449,7 @@ static void test_encodeRsaPublicKey(DWORD dwEncoding)
RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
BOOL ret;
BYTE *buf = NULL;
DWORD bufSize = 0;
DWORD bufSize = 0, i;
/* Try with a bogus blob type */
hdr->bType = 2;
......@@ -1501,19 +1507,24 @@ static void test_encodeRsaPublicKey(DWORD dwEncoding)
ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
LocalFree(buf);
}
/* Finally, all valid, but change the modulus */
/* Finally, all valid */
hdr->aiKeyAlg = CALG_RSA_KEYX;
memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus2,
sizeof(modulus2));
ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
&bufSize);
if (buf)
for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
{
ok(bufSize == rsaPubKeys[1].encoded[1] + 2,
"Expected size %d, got %ld\n", rsaPubKeys[1].encoded[1] + 2, bufSize);
ok(!memcmp(buf, rsaPubKeys[1].encoded, bufSize), "Unexpected value\n");
LocalFree(buf);
memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
if (buf)
{
ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
"Expected size %d, got %ld\n", rsaPubKeys[i].encoded[1] + 2,
bufSize);
ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
"Unexpected value\n");
LocalFree(buf);
}
}
}
......
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