From 69dfea8f443cf7e90c1f9f4ee3021c67360b9942 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Wed, 28 Sep 2005 18:12:29 +0000 Subject: [PATCH] Encode RSA public key modulus as unsigned integer, with tests. --- dlls/crypt32/encode.c | 120 ++++++++++++++++++++++++++++++-------------- dlls/crypt32/tests/encode.c | 35 ++++++++----- 2 files changed, 106 insertions(+), 49 deletions(-) diff --git a/dlls/crypt32/encode.c b/dlls/crypt32/encode.c index 60a1bcdcf53..02574ec321d 100644 --- a/dlls/crypt32/encode.c +++ b/dlls/crypt32/encode.c @@ -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) diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c index 3e02de41d77..d3263a0c7ca 100644 --- a/dlls/crypt32/tests/encode.c +++ b/dlls/crypt32/tests/encode.c @@ -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); + } } } -- 2.11.4.GIT