Commit 1cd9510b authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

crypt32: Implement PKCS_CONTENT_INFO encoding/decoding.

parent 2d00a4f0
......@@ -2126,6 +2126,70 @@ static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret;
DWORD dataLen;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
/* The caller has already checked the tag, no need to check it again.
* Check the outer length is valid by calling CRYPT_GetLen:
*/
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
DWORD innerLen;
pbEncoded += 1 + lenBytes;
/* Check the inner length is valid by calling CRYPT_GetLen again: */
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
{
ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo);
}
}
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY
{
struct AsnDecodeSequenceItem items[] = {
{ ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
{ ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
};
ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo, NULL);
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
}
__ENDTRY
return ret;
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
......@@ -3592,6 +3656,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
case (WORD)X509_AUTHORITY_KEY_ID2:
decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
break;
case (WORD)PKCS_CONTENT_INFO:
decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
break;
case (WORD)X509_SEQUENCE_OF_ANY:
decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
break;
......
......@@ -1349,6 +1349,50 @@ static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret = FALSE;
__TRY
{
const CRYPT_CONTENT_INFO *info =
(const CRYPT_CONTENT_INFO *)pvStructInfo;
if (!info->pszObjId)
SetLastError(E_INVALIDARG);
else
{
struct AsnEncodeSequenceItem items[2] = {
{ info->pszObjId, CRYPT_AsnEncodeOid, 0 },
{ NULL, NULL, 0 },
};
struct AsnConstructedItem constructed = { 0 };
DWORD cItem = 1;
if (info->Content.cbData)
{
constructed.tag = 0;
constructed.pvStructInfo = &info->Content;
constructed.encodeFunc = CRYPT_CopyEncodedBlob;
items[cItem].pvStructInfo = &constructed;
items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
cItem++;
}
ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
}
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
}
__ENDTRY
return ret;
}
static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
DWORD *pcbEncoded)
......@@ -3011,6 +3055,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
case (WORD)X509_UNICODE_NAME:
encodeFunc = CRYPT_AsnEncodeUnicodeName;
break;
case (WORD)PKCS_CONTENT_INFO:
encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
break;
case (WORD)X509_UNICODE_NAME_VALUE:
encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
break;
......
......@@ -4524,6 +4524,113 @@ static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
}
}
static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
0xa0,0x01,0x01 };
static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
0x03,0x02,0x01,0x01 };
static BYTE bogusDER[] = { 1 };
static void test_encodePKCSContentInfo(DWORD dwEncoding)
{
BOOL ret;
BYTE *buf = NULL;
DWORD size = 0;
CRYPT_CONTENT_INFO info = { 0 };
char oid1[] = "1.2.3";
SetLastError(0xdeadbeef);
ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
"Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
SetLastError(0xdeadbeef);
ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
ok(!ret && GetLastError() == E_INVALIDARG,
"Expected E_INVALIDARG, got %x\n", GetLastError());
info.pszObjId = oid1;
ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
if (buf)
{
ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
LocalFree(buf);
}
info.Content.pbData = bogusDER;
info.Content.cbData = sizeof(bogusDER);
ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
if (buf)
{
ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
LocalFree(buf);
}
info.Content.pbData = (BYTE *)ints[0].encoded;
info.Content.cbData = ints[0].encoded[1] + 2;
ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (buf)
{
ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
LocalFree(buf);
}
}
static void test_decodePKCSContentInfo(DWORD dwEncoding)
{
BOOL ret;
LPBYTE buf = NULL;
DWORD size = 0;
CRYPT_CONTENT_INFO *info;
ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
if (buf)
{
info = (CRYPT_CONTENT_INFO *)buf;
ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
info->pszObjId);
ok(info->Content.cbData == 0, "Expected no data, got %d\n",
info->Content.cbData);
LocalFree(buf);
}
SetLastError(0xdeadbeef);
ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
/* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
* I doubt an app depends on that.
*/
ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
GetLastError() == CRYPT_E_ASN1_CORRUPT),
"Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
GetLastError());
ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
intPKCSContentInfo, sizeof(intPKCSContentInfo),
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
if (buf)
{
info = (CRYPT_CONTENT_INFO *)buf;
ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
info->pszObjId);
ok(info->Content.cbData == ints[0].encoded[1] + 2,
"Unexpected size %d\n", info->Content.cbData);
ok(!memcmp(info->Content.pbData, ints[0].encoded,
info->Content.cbData), "Unexpected value\n");
}
}
/* Free *pInfo with HeapFree */
static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
{
......@@ -4731,6 +4838,8 @@ START_TEST(encode)
test_decodeAuthorityKeyId(encodings[i]);
test_encodeAuthorityKeyId2(encodings[i]);
test_decodeAuthorityKeyId2(encodings[i]);
test_encodePKCSContentInfo(encodings[i]);
test_decodePKCSContentInfo(encodings[i]);
}
testPortPublicKeyInfo();
}
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