Encode RSA public key modulus as unsigned integer, with tests.
This commit is contained in:
parent
f469b6f8de
commit
69dfea8f44
|
@ -115,6 +115,9 @@ static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
|
||||||
static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
|
static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
|
||||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
|
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,
|
static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
|
||||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
|
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,
|
static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
|
||||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
|
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 */
|
/* filter for page-fault exceptions */
|
||||||
static WINE_EXCEPTION_FILTER(page_fault)
|
static WINE_EXCEPTION_FILTER(page_fault)
|
||||||
|
@ -1710,7 +1718,7 @@ static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
|
||||||
CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
|
CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
|
||||||
(BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
|
(BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
|
||||||
struct AsnEncodeSequenceItem items[] = {
|
struct AsnEncodeSequenceItem items[] = {
|
||||||
{ &blob, CRYPT_AsnEncodeInteger, 0 },
|
{ &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
|
||||||
{ &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
|
{ &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4385,7 +4393,7 @@ static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
|
||||||
{
|
{
|
||||||
struct AsnDecodeSequenceItem items[] = {
|
struct AsnDecodeSequenceItem items[] = {
|
||||||
{ offsetof(struct DECODED_RSA_PUB_KEY, modulus),
|
{ 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),
|
FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
|
||||||
0 },
|
0 },
|
||||||
{ offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
|
{ offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
|
||||||
|
@ -4801,6 +4809,63 @@ static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (pbEncoded[0] == ASN_INTEGER)
|
||||||
|
{
|
||||||
|
DWORD bytesNeeded, dataLen;
|
||||||
|
|
||||||
|
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
||||||
|
{
|
||||||
|
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
|
||||||
|
|
||||||
|
bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
|
||||||
|
if (!pvStructInfo)
|
||||||
|
*pcbStructInfo = bytesNeeded;
|
||||||
|
else if (*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)
|
||||||
|
{
|
||||||
|
blob->cbData--;
|
||||||
|
blob->pbData++;
|
||||||
|
}
|
||||||
|
if (blob->cbData)
|
||||||
|
{
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
for (i = 0; i < blob->cbData; i++)
|
||||||
|
{
|
||||||
|
blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
|
||||||
|
dataLen - i - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
|
static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
|
||||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||||
|
@ -4809,49 +4874,30 @@ static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
|
||||||
|
|
||||||
__TRY
|
__TRY
|
||||||
{
|
{
|
||||||
if (pbEncoded[0] == ASN_INTEGER)
|
DWORD bytesNeeded;
|
||||||
{
|
|
||||||
DWORD bytesNeeded, dataLen;
|
|
||||||
CRYPT_INTEGER_BLOB *blob;
|
|
||||||
|
|
||||||
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
|
||||||
|
lpszStructType, pbEncoded, cbEncoded,
|
||||||
|
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
|
||||||
|
{
|
||||||
|
if (!pvStructInfo)
|
||||||
|
*pcbStructInfo = bytesNeeded;
|
||||||
|
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
|
||||||
|
pvStructInfo, pcbStructInfo, bytesNeeded)))
|
||||||
{
|
{
|
||||||
bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
|
CRYPT_INTEGER_BLOB *blob;
|
||||||
if (!pvStructInfo)
|
|
||||||
*pcbStructInfo = bytesNeeded;
|
|
||||||
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
|
|
||||||
pvStructInfo, pcbStructInfo, bytesNeeded)))
|
|
||||||
{
|
|
||||||
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
|
|
||||||
|
|
||||||
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
|
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
|
||||||
pvStructInfo = *(BYTE **)pvStructInfo;
|
pvStructInfo = *(BYTE **)pvStructInfo;
|
||||||
blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
|
blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
|
||||||
blob->cbData = dataLen;
|
blob->pbData = (BYTE *)pvStructInfo +
|
||||||
blob->pbData = (BYTE *)pvStructInfo +
|
sizeof(CRYPT_INTEGER_BLOB);
|
||||||
sizeof(CRYPT_INTEGER_BLOB);
|
ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
|
||||||
/* remove leading zero byte if it exists */
|
lpszStructType, pbEncoded, cbEncoded,
|
||||||
if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
|
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
|
||||||
{
|
&bytesNeeded);
|
||||||
blob->cbData--;
|
|
||||||
blob->pbData++;
|
|
||||||
}
|
|
||||||
if (blob->cbData)
|
|
||||||
{
|
|
||||||
DWORD i;
|
|
||||||
|
|
||||||
for (i = 0; i < blob->cbData; i++)
|
|
||||||
blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
|
|
||||||
pbEncoded[1] - i - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
|
||||||
ret = FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
__EXCEPT(page_fault)
|
__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 */
|
/* 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 modulus1[] = { 0,0,0,1,1,1,1,1 };
|
||||||
static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
|
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 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 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
|
struct EncodedRSAPubKey
|
||||||
{
|
{
|
||||||
|
@ -1434,6 +1438,8 @@ struct EncodedRSAPubKey
|
||||||
struct EncodedRSAPubKey rsaPubKeys[] = {
|
struct EncodedRSAPubKey rsaPubKeys[] = {
|
||||||
{ modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
|
{ modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
|
||||||
{ modulus2, sizeof(modulus2), mod2_encoded, 5 },
|
{ modulus2, sizeof(modulus2), mod2_encoded, 5 },
|
||||||
|
{ modulus3, sizeof(modulus3), mod3_encoded, 5 },
|
||||||
|
{ modulus4, sizeof(modulus4), mod4_encoded, 8 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static void test_encodeRsaPublicKey(DWORD dwEncoding)
|
static void test_encodeRsaPublicKey(DWORD dwEncoding)
|
||||||
|
@ -1443,7 +1449,7 @@ static void test_encodeRsaPublicKey(DWORD dwEncoding)
|
||||||
RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
|
RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
BYTE *buf = NULL;
|
BYTE *buf = NULL;
|
||||||
DWORD bufSize = 0;
|
DWORD bufSize = 0, i;
|
||||||
|
|
||||||
/* Try with a bogus blob type */
|
/* Try with a bogus blob type */
|
||||||
hdr->bType = 2;
|
hdr->bType = 2;
|
||||||
|
@ -1501,19 +1507,24 @@ static void test_encodeRsaPublicKey(DWORD dwEncoding)
|
||||||
ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
|
ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
|
||||||
LocalFree(buf);
|
LocalFree(buf);
|
||||||
}
|
}
|
||||||
/* Finally, all valid, but change the modulus */
|
/* Finally, all valid */
|
||||||
hdr->aiKeyAlg = CALG_RSA_KEYX;
|
hdr->aiKeyAlg = CALG_RSA_KEYX;
|
||||||
memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus2,
|
for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
|
||||||
sizeof(modulus2));
|
|
||||||
ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
|
|
||||||
toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
|
|
||||||
&bufSize);
|
|
||||||
if (buf)
|
|
||||||
{
|
{
|
||||||
ok(bufSize == rsaPubKeys[1].encoded[1] + 2,
|
memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
|
||||||
"Expected size %d, got %ld\n", rsaPubKeys[1].encoded[1] + 2, bufSize);
|
rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
|
||||||
ok(!memcmp(buf, rsaPubKeys[1].encoded, bufSize), "Unexpected value\n");
|
ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
|
||||||
LocalFree(buf);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue