crypt32: Implement CRLDistPoints encoding/decoding.

- rewrite sequence decoding to support context-specific tags, and
  eliminate duplicated code
- implement encoding and decoding of CRLDistPoints
This commit is contained in:
Juan Lang 2005-12-16 12:41:28 +01:00 committed by Alexandre Julliard
parent a4af4b95b5
commit 628ede4783
2 changed files with 736 additions and 288 deletions

View File

@ -134,10 +134,11 @@ static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId);
/* Assumes algo->Parameters.pbData is set ahead of time */
/* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
/* Internal function */
static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
@ -402,6 +403,32 @@ static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
return ret;
}
struct AsnEncodeTagSwappedItem
{
BYTE tag;
const void *pvStructInfo;
CryptEncodeObjectExFunc encodeFunc;
};
/* Sort of a wacky hack, it encodes something using the struct
* AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
* given in the struct AsnEncodeTagSwappedItem.
*/
static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret;
const struct AsnEncodeTagSwappedItem *item =
(const struct AsnEncodeTagSwappedItem *)pvStructInfo;
ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
if (ret && pbEncoded)
*pbEncoded = item->tag;
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
@ -2033,6 +2060,145 @@ static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
return ret;
}
static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret = TRUE;
struct AsnEncodeSequenceItem items[3] = { { 0 } };
struct AsnConstructedItem constructed = { 0 };
struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
DWORD cItem = 0, cSwapped = 0;
switch (distPoint->DistPointName.dwDistPointNameChoice)
{
case CRL_DIST_POINT_NO_NAME:
/* do nothing */
break;
case CRL_DIST_POINT_FULL_NAME:
swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
constructed.tag = 0;
constructed.pvStructInfo = &swapped[cSwapped];
constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
items[cItem].pvStructInfo = &constructed;
items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
cSwapped++;
cItem++;
break;
case CRL_DIST_POINT_ISSUER_RDN_NAME:
FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
ret = FALSE;
break;
default:
ret = FALSE;
}
if (ret && distPoint->ReasonFlags.cbData)
{
swapped[cSwapped].tag = ASN_CONTEXT | 1;
swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
items[cItem].pvStructInfo = &swapped[cSwapped];
items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
cSwapped++;
cItem++;
}
if (ret && distPoint->CRLIssuer.cAltEntry)
{
swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
items[cItem].pvStructInfo = &swapped[cSwapped];
items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
cSwapped++;
cItem++;
}
if (ret)
ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
pbEncoded, pcbEncoded);
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret;
__TRY
{
const CRL_DIST_POINTS_INFO *info =
(const CRL_DIST_POINTS_INFO *)pvStructInfo;
if (!info->cDistPoint)
{
SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
ret = FALSE;
}
else
{
DWORD bytesNeeded, dataLen, lenBytes, i;
ret = TRUE;
for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
{
DWORD len;
ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
&len);
if (ret)
dataLen += len;
else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
{
/* Have to propagate index of failing character */
*pcbEncoded = len;
}
}
if (ret)
{
CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + dataLen;
if (!pbEncoded)
{
*pcbEncoded = bytesNeeded;
ret = TRUE;
}
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
for (i = 0; ret && i < info->cDistPoint; i++)
{
DWORD len = dataLen;
ret = CRYPT_AsnEncodeDistPoint(
&info->rgDistPoint[i], pbEncoded, &len);
if (ret)
{
pbEncoded += len;
dataLen -= len;
}
}
}
}
}
}
}
__EXCEPT(page_fault)
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
}
BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
void *pvEncoded, DWORD *pcbEncoded)
@ -2120,6 +2286,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
case (WORD)PKCS_UTC_TIME:
encodeFunc = CRYPT_AsnEncodeUtcTime;
break;
case (WORD)X509_CRL_DIST_POINTS:
encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
break;
default:
FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
}
@ -2306,7 +2475,9 @@ static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
return ret;
}
/* A few of the members need explanation:
/* tag:
* The expected tag of the item. If tag is 0, decodeFunc is called
* regardless of the tag value seen.
* offset:
* A sequence is decoded into a struct. The offset member is the
* offset of this item within that struct.
@ -2316,9 +2487,9 @@ static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
* minSize:
* The minimum amount of space occupied after decoding. You must set this.
* optional:
* If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then
* minSize space is filled with 0 for this member. (Any other failure
* results in CRYPT_AsnDecodeSequence failing.)
* If true, and the tag doesn't match the expected tag for this item,
* or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
* filled with 0 for this member.
* hasPointer, pointerOffset, minSize:
* If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
* the offset within the (outer) struct of the data pointer (or to the
@ -2328,6 +2499,7 @@ static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
*/
struct AsnDecodeSequenceItem
{
BYTE tag;
DWORD offset;
CryptDecodeObjectExFunc decodeFunc;
DWORD minSize;
@ -2337,6 +2509,114 @@ struct AsnDecodeSequenceItem
DWORD size;
};
static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
{
BOOL ret;
DWORD i;
const BYTE *ptr;
ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
for (i = 0, ret = TRUE; ret && i < cItem; i++)
{
if (cbEncoded - (ptr - pbEncoded) != 0)
{
DWORD nextItemLen;
if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
&nextItemLen)))
{
BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
if (ptr[0] == items[i].tag || !items[i].tag)
{
if (nextData && pvStructInfo && items[i].hasPointer)
{
TRACE("Setting next pointer to %p\n",
nextData);
*(BYTE **)((BYTE *)pvStructInfo +
items[i].pointerOffset) = nextData;
}
if (items[i].decodeFunc)
{
if (pvStructInfo)
TRACE("decoding item %ld\n", i);
else
TRACE("sizing item %ld\n", i);
ret = items[i].decodeFunc(dwCertEncodingType,
NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
: NULL, &items[i].size);
if (ret)
{
if (nextData && items[i].hasPointer &&
items[i].size > items[i].minSize)
{
nextData += items[i].size - items[i].minSize;
/* align nextData to DWORD boundaries */
if (items[i].size % sizeof(DWORD))
nextData += sizeof(DWORD) - items[i].size %
sizeof(DWORD);
}
/* Account for alignment padding */
if (items[i].size % sizeof(DWORD))
items[i].size += sizeof(DWORD) -
items[i].size % sizeof(DWORD);
ptr += 1 + nextItemLenBytes + nextItemLen;
}
else if (items[i].optional &&
GetLastError() == CRYPT_E_ASN1_BADTAG)
{
TRACE("skipping optional item %ld\n", i);
items[i].size = items[i].minSize;
SetLastError(NOERROR);
ret = TRUE;
}
else
TRACE("item %ld failed: %08lx\n", i,
GetLastError());
}
else
items[i].size = items[i].minSize;
}
else if (items[i].optional)
{
TRACE("skipping optional item %ld\n", i);
items[i].size = items[i].minSize;
}
else
{
TRACE("tag %02x doesn't match expected %02x\n",
ptr[0], items[i].tag);
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
}
}
else if (items[i].optional)
{
TRACE("missing optional item %ld, skipping\n", i);
items[i].size = items[i].minSize;
}
else
{
TRACE("not enough bytes for item %ld, failing\n", i);
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
}
if (cbEncoded - (ptr - pbEncoded) != 0)
{
TRACE("%ld remaining bytes, failing\n", cbEncoded -
(ptr - pbEncoded));
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
return ret;
}
/* This decodes an arbitrary sequence into a contiguous block of memory
* (basically, a struct.) Each element being decoded is described by a struct
* AsnDecodeSequenceItem, see above.
@ -2363,72 +2643,19 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
DWORD i, bytesNeeded = 0, minSize = 0;
const BYTE *ptr;
DWORD i;
ptr = pbEncoded + 1 + lenBytes;
for (i = 0; ret && i < cItem; i++)
{
DWORD nextItemLen;
minSize += items[i].minSize;
if (cbEncoded - (ptr - pbEncoded) != 0)
{
if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
&nextItemLen)))
{
BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
if (items[i].decodeFunc)
{
TRACE("sizing item %ld\n", i);
ret = items[i].decodeFunc(dwCertEncodingType, NULL,
ptr, 1 + nextItemLenBytes + nextItemLen,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
&items[i].size);
ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
cbEncoded, dwFlags, NULL, NULL);
if (ret)
{
/* Account for alignment padding */
DWORD bytesNeeded = 0, structSize = 0;
for (i = 0; i < cItem; i++)
{
bytesNeeded += items[i].size;
if (items[i].size % sizeof(DWORD))
bytesNeeded += sizeof(DWORD) -
items[i].size % sizeof(DWORD);
ptr += 1 + nextItemLenBytes + nextItemLen;
structSize += items[i].minSize;
}
else if (items[i].optional &&
GetLastError() == CRYPT_E_ASN1_BADTAG)
{
TRACE("skipping optional item %ld\n", i);
bytesNeeded += items[i].minSize;
SetLastError(NOERROR);
ret = TRUE;
}
else
TRACE("item %ld failed: %08lx\n", i,
GetLastError());
}
else
bytesNeeded += items[i].minSize;
}
}
else if (items[i].optional)
bytesNeeded += items[i].minSize;
else
{
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
}
if (cbEncoded - (ptr - pbEncoded) != 0)
{
TRACE("%ld remaining bytes, failing\n", cbEncoded -
(ptr - pbEncoded));
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
if (ret)
{
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
@ -2441,69 +2668,10 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
if (startingPointer)
nextData = (BYTE *)startingPointer;
else
nextData = (BYTE *)pvStructInfo + minSize;
memset(pvStructInfo, 0, minSize);
ptr = pbEncoded + 1 + lenBytes;
for (i = 0; ret && i < cItem; i++)
{
if (cbEncoded - (ptr - pbEncoded) != 0)
{
DWORD nextItemLen;
BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
&nextItemLen);
if (items[i].hasPointer)
{
TRACE("Setting next pointer to %p\n", nextData);
*(BYTE **)((BYTE *)pvStructInfo +
items[i].pointerOffset) = nextData;
}
if (items[i].decodeFunc)
{
TRACE("decoding item %ld, offset %ld (%p)\n",
i, items[i].offset,
(BYTE *)pvStructInfo + items[i].offset);
ret = items[i].decodeFunc(dwCertEncodingType,
NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
(BYTE *)pvStructInfo + items[i].offset,
&items[i].size);
if (!ret)
TRACE("item %ld failed: %08lx\n", i,
GetLastError());
}
else
items[i].size = items[i].minSize;
if (ret)
{
if (items[i].hasPointer &&
items[i].size > items[i].minSize)
{
nextData += items[i].size -
items[i].minSize;
/* align nextData to DWORD boundaries */
if (items[i].size % sizeof(DWORD))
{
nextData += sizeof(DWORD) -
items[i].size % sizeof(DWORD);
}
}
ptr += 1 + nextItemLenBytes + nextItemLen;
}
else if (items[i].optional &&
GetLastError() == CRYPT_E_ASN1_BADTAG)
{
SetLastError(NOERROR);
ret = TRUE;
}
}
else if (!items[i].optional)
{
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
}
nextData = (BYTE *)pvStructInfo + structSize;
memset(pvStructInfo, 0, structSize);
ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
}
}
}
@ -2790,14 +2958,14 @@ static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
__TRY
{
struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
{ 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
{ offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm),
CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
FALSE, TRUE, offsetof(CERT_SIGNED_CONTENT_INFO,
SignatureAlgorithm.pszObjId), 0 },
{ offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
{ ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
{ ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
};
@ -2817,14 +2985,12 @@ static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
return ret;
}
/* Internal function */
static BOOL WINAPI CRYPT_AsnDecodeCertVersion(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_CONTEXT | ASN_CONSTRUCTOR))
{
DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
@ -2835,12 +3001,6 @@ static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
pvStructInfo, pcbStructInfo);
}
}
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
return ret;
}
@ -2851,9 +3011,9 @@ static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
BOOL ret;
struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
{ 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
{ offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
{ 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
};
@ -2863,14 +3023,12 @@ static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
return ret;
}
/* Internal function */
static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(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_CONTEXT | ASN_CONSTRUCTOR | 3))
{
DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
@ -2881,12 +3039,6 @@ static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo);
}
}
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
return ret;
}
@ -2902,34 +3054,39 @@ static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
__TRY
{
struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_INFO, dwVersion), CRYPT_AsnDecodeCertVersion,
sizeof(DWORD), TRUE, FALSE, 0, 0 },
{ offsetof(CERT_INFO, SerialNumber), CRYPT_AsnDecodeIntegerInternal,
sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
SerialNumber.pbData), 0 },
{ offsetof(CERT_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CERT_INFO,
SignatureAlgorithm.pszObjId), 0 },
{ offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
{ ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
{ ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
{ ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
{ 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
Issuer.pbData) },
{ offsetof(CERT_INFO, NotBefore), CRYPT_AsnDecodeValidity,
sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE, FALSE, 0 },
{ offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
{ ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
FALSE, 0 },
{ 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
Subject.pbData) },
{ offsetof(CERT_INFO, SubjectPublicKeyInfo), CRYPT_AsnDecodePubKeyInfo,
sizeof(CERT_PUBLIC_KEY_INFO), FALSE, TRUE, offsetof(CERT_INFO,
/* jil FIXME: shouldn't this have an internal version, which expects
* the pbData to be set?
*/
{ ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
CRYPT_AsnDecodePubKeyInfo, sizeof(CERT_PUBLIC_KEY_INFO), FALSE,
TRUE, offsetof(CERT_INFO,
SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
{ offsetof(CERT_INFO, IssuerUniqueId), CRYPT_AsnDecodeBitsInternal,
sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO,
IssuerUniqueId.pbData), 0 },
{ offsetof(CERT_INFO, SubjectUniqueId), CRYPT_AsnDecodeBitsInternal,
sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO,
SubjectUniqueId.pbData), 0 },
{ offsetof(CERT_INFO, cExtension), CRYPT_AsnDecodeCertExtensions,
sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CERT_INFO,
rgExtension), 0 },
{ ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
{ ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
{ ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
offsetof(CERT_INFO, rgExtension), 0 },
};
ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
@ -2951,14 +3108,14 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
{
BOOL ret;
struct AsnDecodeSequenceItem items[] = {
{ offsetof(CRL_ENTRY, SerialNumber), CRYPT_AsnDecodeIntegerInternal,
sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CRL_ENTRY,
SerialNumber.pbData), 0 },
{ offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
{ ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
{ 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
sizeof(FILETIME), FALSE, FALSE, 0 },
{ offsetof(CRL_ENTRY, cExtension), CRYPT_AsnDecodeExtensionsInternal,
sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CRL_ENTRY,
rgExtension), 0 },
{ ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
offsetof(CRL_ENTRY, rgExtension), 0 },
};
PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
@ -2971,12 +3128,7 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
return ret;
}
typedef struct _WINE_CRL_ENTRIES {
DWORD cCRLEntry;
PCRL_ENTRY rgCRLEntry;
} WINE_CRL_ENTRIES, *PWINE_CRL_ENTRIES;
/* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has
/* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
* been set prior to calling.
*/
static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
@ -2987,14 +3139,14 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
offsetof(CRL_ENTRY, SerialNumber.pbData) };
PWINE_CRL_ENTRIES entries = (PWINE_CRL_ENTRIES)pvStructInfo;
struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo,
entries ? entries->rgCRLEntry : NULL);
entries ? entries->rgItems : NULL);
TRACE("Returning %d (%08lx)\n", ret, GetLastError());
return ret;
}
@ -3011,24 +3163,24 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
__TRY
{
struct AsnDecodeSequenceItem items[] = {
{ offsetof(CRL_INFO, dwVersion), CRYPT_AsnDecodeCertVersion,
sizeof(DWORD), TRUE, FALSE, 0, 0 },
{ offsetof(CRL_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CRL_INFO,
SignatureAlgorithm.pszObjId), 0 },
{ offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
{ ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CRL_INFO, dwVersion),
CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
{ ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
{ 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
Issuer.pbData) },
{ offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
{ 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
sizeof(FILETIME), FALSE, FALSE, 0 },
{ offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
{ 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
sizeof(FILETIME), TRUE, FALSE, 0 },
{ offsetof(CRL_INFO, cCRLEntry), CRYPT_AsnDecodeCRLEntries,
sizeof(WINE_CRL_ENTRIES), TRUE, TRUE, offsetof(CRL_INFO,
rgCRLEntry), 0 },
{ ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
offsetof(CRL_INFO, rgCRLEntry), 0 },
/* Note that the extensions are ignored by MS, so I'll ignore them too
*/
{ offsetof(CRL_INFO, cExtension), NULL,
{ 0, offsetof(CRL_INFO, cExtension), NULL,
sizeof(CERT_EXTENSIONS), TRUE, FALSE, 0 },
};
@ -3079,13 +3231,14 @@ static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_EXTENSION, pszObjId), CRYPT_AsnDecodeOidWrapper,
sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_EXTENSION, pszObjId), 0 },
{ offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
{ ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE,
offsetof(CERT_EXTENSION, pszObjId), 0 },
{ ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
sizeof(BOOL), TRUE, FALSE, 0, 0 },
{ offsetof(CERT_EXTENSION, Value), CRYPT_AsnDecodeOctetsInternal,
sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE, offsetof(CERT_EXTENSION,
Value.pbData) },
{ ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
offsetof(CERT_EXTENSION, Value.pbData) },
};
BOOL ret = TRUE;
PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
@ -3394,9 +3547,10 @@ static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
__TRY
{
struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_RDN_ATTR, pszObjId), CRYPT_AsnDecodeOidWrapper,
sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_RDN_ATTR, pszObjId), 0 },
{ offsetof(CERT_RDN_ATTR, dwValueType), CRYPT_AsnDecodeNameValue,
{ ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE,
offsetof(CERT_RDN_ATTR, pszObjId), 0 },
{ 0, offsetof(CERT_RDN_ATTR, dwValueType), CRYPT_AsnDecodeNameValue,
sizeof(CERT_NAME_VALUE), FALSE, TRUE, offsetof(CERT_RDN_ATTR,
Value.pbData), 0 },
};
@ -3514,10 +3668,10 @@ static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
(CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
BOOL ret = TRUE;
struct AsnDecodeSequenceItem items[] = {
{ offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
{ ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE,
offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
{ offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
{ 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
};
@ -3545,11 +3699,11 @@ static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
__TRY
{
struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
{ ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
Algorithm.pszObjId) },
{ offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
{ ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
};
@ -3578,11 +3732,6 @@ static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
SetLastError(CRYPT_E_ASN1_CORRUPT);
return FALSE;
}
if (pbEncoded[0] != ASN_BOOL)
{
SetLastError(CRYPT_E_ASN1_BADTAG);
return FALSE;
}
if (GET_LEN_BYTES(pbEncoded[1]) > 1)
{
SetLastError(CRYPT_E_ASN1_CORRUPT);
@ -3696,6 +3845,8 @@ static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
entry->u.pwszURL[i] =
(WCHAR)pbEncoded[1 + lenBytes + i];
entry->u.pwszURL[i] = 0;
TRACE("URL is %p (%s)\n", entry->u.pwszURL,
debugstr_w(entry->u.pwszURL));
break;
}
case 7: /* iPAddress */
@ -3714,6 +3865,26 @@ static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret = TRUE;
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
if (info)
TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
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)
@ -3753,6 +3924,9 @@ static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
{
BOOL ret = TRUE;
TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo);
if (cbEncoded)
{
if (pbEncoded[0] == ASN_INTEGER)
@ -3801,11 +3975,11 @@ static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
__TRY
{
struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA), CRYPT_AsnDecodeBool,
sizeof(BOOL), TRUE, FALSE, 0, 0 },
{ offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fPathLenConstraint),
CRYPT_AsnDecodePathLenConstraint, sizeof(struct PATH_LEN_CONSTRAINT),
TRUE, FALSE, 0, 0 },
{ ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
{ ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
};
ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
@ -3838,11 +4012,11 @@ static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
__TRY
{
struct AsnDecodeSequenceItem items[] = {
{ offsetof(struct DECODED_RSA_PUB_KEY, modulus),
{ ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
0 },
{ offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
{ ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
};
struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
@ -3900,14 +4074,11 @@ static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret;
DWORD bytesNeeded, dataLen;
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
if (pbEncoded[0] == ASN_OCTETSTRING)
{
DWORD bytesNeeded, dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
@ -3940,12 +4111,6 @@ static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
}
}
}
}
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
return ret;
}
@ -3962,7 +4127,17 @@ static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
{
DWORD bytesNeeded;
if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
if (!cbEncoded)
{
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
else if (pbEncoded[0] != ASN_OCTETSTRING)
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
lpszStructType, pbEncoded, cbEncoded,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
{
@ -3983,11 +4158,6 @@ static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
&bytesNeeded);
}
}
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
}
__EXCEPT(page_fault)
{
@ -4830,6 +5000,57 @@ static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
struct AsnDecodeSequenceItem items[] = {
{ ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
DistPointName), CRYPT_AsnDecodeAltNameInternal,
sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
DistPointName.u.FullName.rgAltEntry), 0 },
{ ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
{ ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
};
BOOL ret;
ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret;
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY
{
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo, NULL);
}
__EXCEPT(page_fault)
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
}
BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
@ -4927,6 +5148,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
case (WORD)PKCS_UTC_TIME:
decodeFunc = CRYPT_AsnDecodeUtcTime;
break;
case (WORD)X509_CRL_DIST_POINTS:
decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
break;
default:
FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
}

View File

@ -1379,14 +1379,15 @@ static void test_decodeBasicConstraints(DWORD dwEncoding)
ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
constraints2[i].encoded, constraints2[i].encoded[1] + 2,
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
ok(ret, "CryptDecodeObjectEx failed for item %ld: %08lx\n", i,
GetLastError());
if (buf)
{
CERT_BASIC_CONSTRAINTS2_INFO *info =
(CERT_BASIC_CONSTRAINTS2_INFO *)buf;
ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
"Unexpected value\n");
"Unexpected value for item %ld\n", i);
LocalFree(buf);
}
}
@ -2222,6 +2223,227 @@ static void test_decodeCert(DWORD dwEncoding)
}
}
static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
0x00, 0x03 };
static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
0x2e, 0x6f, 0x72, 0x67 };
static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
CRL_REASON_AFFILIATION_CHANGED;
static void test_encodeCRLDistPoints(DWORD dwEncoding)
{
CRL_DIST_POINTS_INFO info = { 0 };
CRL_DIST_POINT point = { { 0 } };
CERT_ALT_NAME_ENTRY entry = { 0 };
BOOL ret;
BYTE *buf = NULL;
DWORD size = 0;
/* Test with an empty info */
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
/* Test with one empty dist point */
info.cDistPoint = 1;
info.rgDistPoint = &point;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (buf)
{
ok(size == sizeof(emptyDistPoint), "Expected size %d, got %ld\n",
sizeof(emptyDistPoint), size);
ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
LocalFree(buf);
}
/* A dist point with an invalid name */
point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
entry.dwAltNameChoice = CERT_ALT_NAME_URL;
entry.pwszURL = (LPWSTR)nihongoURL;
point.DistPointName.FullName.cAltEntry = 1;
point.DistPointName.FullName.rgAltEntry = &entry;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
"Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
/* The first invalid character is at index 7 */
ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
"Expected invalid char at index 7, got %ld\n",
GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
/* A dist point with (just) a valid name */
entry.pwszURL = (LPWSTR)url;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (buf)
{
ok(size == sizeof(distPointWithUrl), "Expected size %d, got %ld\n",
sizeof(distPointWithUrl), size);
ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
LocalFree(buf);
}
/* A dist point with (just) reason flags */
point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
point.ReasonFlags.cbData = sizeof(crlReason);
point.ReasonFlags.pbData = (LPBYTE)&crlReason;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (buf)
{
ok(size == sizeof(distPointWithReason), "Expected size %d, got %ld\n",
sizeof(distPointWithReason), size);
ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
LocalFree(buf);
}
/* A dist point with just an issuer */
point.ReasonFlags.cbData = 0;
point.CRLIssuer.cAltEntry = 1;
point.CRLIssuer.rgAltEntry = &entry;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (buf)
{
ok(size == sizeof(distPointWithIssuer), "Expected size %d, got %ld\n",
sizeof(distPointWithIssuer), size);
ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
LocalFree(buf);
}
/* A dist point with both a name and an issuer */
point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (buf)
{
ok(size == sizeof(distPointWithUrlAndIssuer),
"Expected size %d, got %ld\n", sizeof(distPointWithUrlAndIssuer),
size);
ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
LocalFree(buf);
}
}
static void test_decodeCRLDistPoints(DWORD dwEncoding)
{
BOOL ret;
BYTE *buf = NULL;
DWORD size = 0;
PCRL_DIST_POINTS_INFO info;
PCRL_DIST_POINT point;
PCERT_ALT_NAME_ENTRY entry;
ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
(BYTE *)&buf, &size);
if (ret)
{
info = (PCRL_DIST_POINTS_INFO)buf;
ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
"Expected size at least %d, got %ld\n",
sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
info->cDistPoint);
point = info->rgDistPoint;
ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
"Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
point->DistPointName.dwDistPointNameChoice);
ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
LocalFree(buf);
}
ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
(BYTE *)&buf, &size);
if (ret)
{
info = (PCRL_DIST_POINTS_INFO)buf;
ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
"Expected size at least %d, got %ld\n",
sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
info->cDistPoint);
point = info->rgDistPoint;
ok(point->DistPointName.dwDistPointNameChoice ==
CRL_DIST_POINT_FULL_NAME,
"Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
point->DistPointName.dwDistPointNameChoice);
ok(point->DistPointName.FullName.cAltEntry == 1,
"Expected 1 name entry, got %ld\n",
point->DistPointName.FullName.cAltEntry);
entry = point->DistPointName.FullName.rgAltEntry;
ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
"Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
ok(!lstrcmpW(entry->pwszURL, url), "Unexpected name\n");
ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
LocalFree(buf);
}
ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
NULL, (BYTE *)&buf, &size);
if (ret)
{
info = (PCRL_DIST_POINTS_INFO)buf;
ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
"Expected size at least %d, got %ld\n",
sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
info->cDistPoint);
point = info->rgDistPoint;
ok(point->DistPointName.dwDistPointNameChoice ==
CRL_DIST_POINT_NO_NAME,
"Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
point->DistPointName.dwDistPointNameChoice);
ok(point->ReasonFlags.cbData == sizeof(crlReason),
"Expected reason length\n");
ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
"Unexpected reason\n");
ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
LocalFree(buf);
}
ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (ret)
{
info = (PCRL_DIST_POINTS_INFO)buf;
ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
"Expected size at least %d, got %ld\n",
sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
info->cDistPoint);
point = info->rgDistPoint;
ok(point->DistPointName.dwDistPointNameChoice ==
CRL_DIST_POINT_FULL_NAME,
"Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
point->DistPointName.dwDistPointNameChoice);
ok(point->DistPointName.FullName.cAltEntry == 1,
"Expected 1 name entry, got %ld\n",
point->DistPointName.FullName.cAltEntry);
entry = point->DistPointName.FullName.rgAltEntry;
ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
"Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
ok(!lstrcmpW(entry->pwszURL, url), "Unexpected name\n");
ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
ok(point->CRLIssuer.cAltEntry == 1,
"Expected 1 issuer entry, got %ld\n", point->CRLIssuer.cAltEntry);
entry = point->CRLIssuer.rgAltEntry;
ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
"Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
ok(!lstrcmpW(entry->pwszURL, url), "Unexpected name\n");
LocalFree(buf);
}
}
static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x5a };
@ -2594,6 +2816,8 @@ START_TEST(encode)
test_decodeCertToBeSigned(encodings[i]);
test_encodeCert(encodings[i]);
test_decodeCert(encodings[i]);
test_encodeCRLDistPoints(encodings[i]);
test_decodeCRLDistPoints(encodings[i]);
test_encodeCRLToBeSigned(encodings[i]);
test_decodeCRLToBeSigned(encodings[i]);
}