crypt32: Implement PKCS_ATTRIBUTES encoding/decoding.
This commit is contained in:
parent
74addd636e
commit
e1f83a7abf
|
@ -536,7 +536,7 @@ static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
|
|||
for (ptr = pbEncoded + 1 + lenBytes; ret &&
|
||||
ptr - pbEncoded - 1 - lenBytes < dataLen; )
|
||||
{
|
||||
DWORD itemLenBytes, itemDataLen, size;
|
||||
DWORD itemLenBytes, itemDataLen, size = 0;
|
||||
|
||||
itemLenBytes = GET_LEN_BYTES(ptr[1]);
|
||||
/* Each item decoded may not tolerate extraneous bytes, so
|
||||
|
@ -1829,16 +1829,81 @@ static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
|
|||
CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
|
||||
offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
|
||||
};
|
||||
PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
|
||||
|
||||
ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
|
||||
sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, pcbStructInfo, NULL);
|
||||
pDecodePara, pvStructInfo, pcbStructInfo, attr ? attr->pszObjId :
|
||||
NULL);
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
__ENDTRY
|
||||
TRACE("returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
|
||||
DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
|
||||
DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
|
||||
void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
|
||||
CRYPT_AsnDecodePKCSAttribute, sizeof(CRYPT_ATTRIBUTE), TRUE,
|
||||
offsetof(CRYPT_ATTRIBUTE, pszObjId) };
|
||||
PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
|
||||
BOOL ret;
|
||||
|
||||
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, pcbStructInfo, attrs ? attrs->rgAttr :
|
||||
NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(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
|
||||
{
|
||||
DWORD bytesNeeded;
|
||||
|
||||
if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
|
||||
lpszStructType, pbEncoded, cbEncoded,
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
|
||||
{
|
||||
if (!pvStructInfo)
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
|
||||
pvStructInfo, pcbStructInfo, bytesNeeded)))
|
||||
{
|
||||
PCRYPT_ATTRIBUTES attrs;
|
||||
|
||||
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
|
||||
pvStructInfo = *(BYTE **)pvStructInfo;
|
||||
attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
|
||||
attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
|
||||
sizeof(CRYPT_ATTRIBUTES));
|
||||
ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
|
||||
lpszStructType, pbEncoded, cbEncoded,
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
|
||||
&bytesNeeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
__ENDTRY
|
||||
TRACE("returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -3721,6 +3786,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)X509_ENHANCED_KEY_USAGE:
|
||||
decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
|
||||
break;
|
||||
case (WORD)PKCS_ATTRIBUTES:
|
||||
decodeFunc = CRYPT_AsnDecodePKCSAttributes;
|
||||
break;
|
||||
case (WORD)X509_ISSUING_DIST_POINT:
|
||||
decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
|
||||
break;
|
||||
|
|
|
@ -1386,6 +1386,63 @@ static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
CRYPT_SET_OF setOf = { 0, NULL };
|
||||
|
||||
__TRY
|
||||
{
|
||||
DWORD i;
|
||||
const CRYPT_ATTRIBUTES *attributes =
|
||||
(const CRYPT_ATTRIBUTES *)pvStructInfo;
|
||||
|
||||
ret = TRUE;
|
||||
if (attributes->cAttr)
|
||||
{
|
||||
setOf.cValue = attributes->cAttr;
|
||||
setOf.rgValue = CryptMemAlloc(attributes->cAttr *
|
||||
sizeof(CRYPT_DER_BLOB));
|
||||
if (!setOf.rgValue)
|
||||
ret = FALSE;
|
||||
else
|
||||
memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
|
||||
}
|
||||
for (i = 0; ret && i < attributes->cAttr; i++)
|
||||
{
|
||||
ret = CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType, NULL,
|
||||
&attributes->rgAttr[i], 0, NULL, NULL, &setOf.rgValue[i].cbData);
|
||||
if (ret)
|
||||
{
|
||||
setOf.rgValue[i].pbData =
|
||||
CryptMemAlloc(setOf.rgValue[i].cbData);
|
||||
if (!setOf.rgValue[i].pbData)
|
||||
ret = FALSE;
|
||||
else
|
||||
{
|
||||
ret = CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType, NULL,
|
||||
&attributes->rgAttr[i], 0, NULL, setOf.rgValue[i].pbData,
|
||||
&setOf.rgValue[i].cbData);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, dwFlags,
|
||||
pEncodePara, pbEncoded, pcbEncoded);
|
||||
for (i = 0; i < setOf.cValue; i++)
|
||||
CryptMemFree(setOf.rgValue[i].pbData);
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
__ENDTRY
|
||||
CryptMemFree(setOf.rgValue);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
|
@ -3138,6 +3195,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)X509_ENHANCED_KEY_USAGE:
|
||||
encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
|
||||
break;
|
||||
case (WORD)PKCS_ATTRIBUTES:
|
||||
encodeFunc = CRYPT_AsnEncodePKCSAttributes;
|
||||
break;
|
||||
case (WORD)X509_ISSUING_DIST_POINT:
|
||||
encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
|
||||
break;
|
||||
|
|
|
@ -4740,6 +4740,123 @@ static void test_decodePKCSAttribute(DWORD dwEncoding)
|
|||
attr->rgValue[0].cbData), "Unexpected value\n");
|
||||
}
|
||||
}
|
||||
|
||||
static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
|
||||
static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
|
||||
0x2a,0x03,0x31,0x00 };
|
||||
static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
|
||||
0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
|
||||
|
||||
static void test_encodePKCSAttributes(DWORD dwEncoding)
|
||||
{
|
||||
CRYPT_ATTRIBUTES attributes = { 0 };
|
||||
CRYPT_ATTRIBUTE attr[2] = { { 0 } };
|
||||
CRYPT_ATTR_BLOB blob;
|
||||
BOOL ret;
|
||||
LPBYTE buf = NULL;
|
||||
DWORD size = 0;
|
||||
char oid1[] = "1.2.3", oid2[] = "1.5.6";
|
||||
|
||||
ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
|
||||
ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
attributes.cAttr = 1;
|
||||
attributes.rgAttr = attr;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %x\n", GetLastError());
|
||||
attr[0].pszObjId = oid1;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
|
||||
ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
attr[1].pszObjId = oid2;
|
||||
attr[1].cValue = 1;
|
||||
attr[1].rgValue = &blob;
|
||||
blob.pbData = (BYTE *)ints[0].encoded;
|
||||
blob.cbData = ints[0].encoded[1] + 2;
|
||||
attributes.cAttr = 2;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
|
||||
ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_decodePKCSAttributes(DWORD dwEncoding)
|
||||
{
|
||||
BOOL ret;
|
||||
LPBYTE buf = NULL;
|
||||
DWORD size = 0;
|
||||
CRYPT_ATTRIBUTES *attributes;
|
||||
|
||||
ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
|
||||
emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
|
||||
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
attributes = (CRYPT_ATTRIBUTES *)buf;
|
||||
ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
|
||||
attributes->cAttr);
|
||||
LocalFree(buf);
|
||||
}
|
||||
ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
|
||||
singlePKCSAttributes, sizeof(singlePKCSAttributes),
|
||||
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
attributes = (CRYPT_ATTRIBUTES *)buf;
|
||||
ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
|
||||
attributes->cAttr);
|
||||
ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
|
||||
"Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
|
||||
ok(attributes->rgAttr[0].cValue == 0,
|
||||
"Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
|
||||
LocalFree(buf);
|
||||
}
|
||||
ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
|
||||
doublePKCSAttributes, sizeof(doublePKCSAttributes),
|
||||
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
attributes = (CRYPT_ATTRIBUTES *)buf;
|
||||
ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
|
||||
attributes->cAttr);
|
||||
ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
|
||||
"Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
|
||||
ok(attributes->rgAttr[0].cValue == 0,
|
||||
"Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
|
||||
ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
|
||||
"Expected 1.5.6, got %s", attributes->rgAttr[1].pszObjId);
|
||||
ok(attributes->rgAttr[1].cValue == 1,
|
||||
"Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
|
||||
ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
|
||||
"Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
|
||||
ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
|
||||
attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free *pInfo with HeapFree */
|
||||
static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
|
||||
{
|
||||
|
@ -4951,6 +5068,8 @@ START_TEST(encode)
|
|||
test_decodePKCSContentInfo(encodings[i]);
|
||||
test_encodePKCSAttribute(encodings[i]);
|
||||
test_decodePKCSAttribute(encodings[i]);
|
||||
test_encodePKCSAttributes(encodings[i]);
|
||||
test_decodePKCSAttributes(encodings[i]);
|
||||
}
|
||||
testPortPublicKeyInfo();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue