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,35 +4809,36 @@ static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
return ret; return ret;
} }
static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, DWORD *pcbStructInfo)
{ {
BOOL ret; BOOL ret;
__TRY
{
if (pbEncoded[0] == ASN_INTEGER) if (pbEncoded[0] == ASN_INTEGER)
{ {
DWORD bytesNeeded, dataLen; DWORD bytesNeeded, dataLen;
CRYPT_INTEGER_BLOB *blob;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{ {
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB); bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
if (!pvStructInfo) if (!pvStructInfo)
*pcbStructInfo = bytesNeeded; *pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, else if (*pcbStructInfo < bytesNeeded)
pvStructInfo, pcbStructInfo, bytesNeeded)))
{ {
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); *pcbStructInfo = bytesNeeded;
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
else
{
CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
blob->cbData = dataLen; blob->cbData = dataLen;
blob->pbData = (BYTE *)pvStructInfo + assert(blob->pbData);
sizeof(CRYPT_INTEGER_BLOB);
/* remove leading zero byte if it exists */ /* remove leading zero byte if it exists */
if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0) if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
{ {
@ -4841,8 +4850,10 @@ static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
DWORD i; DWORD i;
for (i = 0; i < blob->cbData; i++) for (i = 0; i < blob->cbData; i++)
{
blob->pbData[i] = *(pbEncoded + 1 + lenBytes + blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
pbEncoded[1] - i - 1); dataLen - i - 1);
}
} }
} }
} }
@ -4852,6 +4863,41 @@ static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
SetLastError(CRYPT_E_ASN1_BADTAG); SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE; 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)))
{
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) __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,20 +1507,25 @@ 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)); {
memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB, ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
&bufSize); ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
if (buf) if (buf)
{ {
ok(bufSize == rsaPubKeys[1].encoded[1] + 2, ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
"Expected size %d, got %ld\n", rsaPubKeys[1].encoded[1] + 2, bufSize); "Expected size %d, got %ld\n", rsaPubKeys[i].encoded[1] + 2,
ok(!memcmp(buf, rsaPubKeys[1].encoded, bufSize), "Unexpected value\n"); bufSize);
ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
"Unexpected value\n");
LocalFree(buf); LocalFree(buf);
} }
}
} }
static void test_decodeRsaPublicKey(DWORD dwEncoding) static void test_decodeRsaPublicKey(DWORD dwEncoding)