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

This commit is contained in:
Juan Lang 2005-09-28 18:12:29 +00:00 committed by Alexandre Julliard
parent f469b6f8de
commit 69dfea8f44
2 changed files with 109 additions and 52 deletions

View File

@ -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)
{ {

View File

@ -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);
}
} }
} }